0
votes

I have a category method that does somethign like this:

@implementation NSData (additions)
- (id)someFunc {

char *buffer = malloc(255);
NSUInteger length = 0;
while (true) {
    // . . . fill buffer[length++];
}

realloc(buffer, length);
return [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:NO];
}

I am then trying to write the returned data (well call this NSData *fileData):

NSError *error;
NSData fileData = [NSData someFunc];
[fileData writeToFile:somePath options:NSDataWritingAtomic error:&error];

I get an error:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x20deffd0 {NSFilePath=/Users/user/Library/Application Support/iPhone Simulator/4.3/Applications/4C315580-153D-4FA7-9474-E17B58832515/Library/Caches/file.pdf, NSUnderlyingError=0x20de1fe0 "The operation couldn’t be completed. Bad address"}

The path exists and is valid. I think the issue is the returned NSData is just a light wrapper around an array allocated with malloc and that writeToFile does not know how to handle this. Does anyone see what I am doing wrong?

2
You need to save the address returned by realloc: buffer = realloc(buffer, length);DarkDust
@DarkDust That was the problem, please make that an answer and I will accept it.Tom Fobear

2 Answers

1
votes

When you call realloc you must save the returned pointer, since realloc may allocate a new buffer and copy the content of the old location to that new location. Afterwards the old location is freed and thus invalid. A different malloc call may overwrite that old location.

So you need to do:

buffer = realloc(buffer, length);
0
votes

That code doesn't make any sense.

  • show the code that you use to fill the buffer

  • you have a malloc(), why do you realloc() after the loop? That is a waste of cycles and, if the goal were to expand the buffer if the input data were too long, it won't work as written.

  • you must check the return value from writeToFile:options:error: to know whether or not there is an error; you cannot check the error directly.

  • also, don't stick a category like that onto an existing class. In general, it is indicative of an architecture that is fragile and poorly layered. If you do go this route, at least prefix your method with something unique.

It isn't clear why that particular error came up. That path seems a little wonky maybe, how are you generating it?