Question

I've been using

NSMutableData* mutableData = [NSMutableData dataWithLength: someLength];
void* bitmapData = [mutableData mutableBytes];
CGContextRef context = CGBitmapContextCreate(bitmapData,...);
// ...use context
CGContextRelease(context);

I have an autorelease pool in place, but when looking at this in Instruments, mutableData doesn't seem to be deallocated.
I thought of using alloc/init like below, but I'm not sure if sending release would purge bitmapData as well.

NSMutableData* mutableData = [[NSMutableData alloc] initWithLength: someLength];
void* bitmapData = [mutableData mutableBytes];
[mutableData release];
//...

What's the proper way of using NSMutableData here?

I thought using NSMutableData instead of malloc() and free() would be convenient because it'll be autoreleased. but now I'm not sure if that's true.

Was it helpful?

Solution

When you say mutableData doesn't seem to be deallocated, do you mean at the point of CGContextRelease(), or do you mean it never deallocates and it leaks every time you run this?

In your first example, you would not expect mutableData to deallocate until the autorelease pool drains (generally at the end of the event loop), because you used -dataWithLength:. In your second example, it's undefined whether mutableData would be released. The call to -mutableBytes might apply a retain and autorelease to ensure the pointer is valid for the rest of the event loop (this is pretty common with these kinds of methods), but the docs don't say, so your second example is undefined behavior if you use bitmapData later.

Now if mutableData leaks, then you're likely over-retaining it somewhere else.

OTHER TIPS

Asking an instance of NSMutableData for its mutableBytes simply returns a pointer to the existing (already allocated) buffer that it manages for you. It does not have any effect on the memory from a management perspective.

So, in your first example, the fact that mutableData doesn't appear to be deallocated when looking at it in Instruments could be related to the autorelease pool environment at the time. Does the code using mutableData in that way have an NSAutoreleasePool in place? Do you see warnings in the console like "autorelease called with no pool in place; just leaking"? If so, you just need to wrap the code in:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// bitmap drawing code here
[pool drain];

In the second sample, you could use alloc/init on the NSMutableData instance, but you would need to release it after you were done using the pointer you get from mutableBytes. The pointer will be pointing to deallocated (freed) memory after you call release, and accessing it will result in the dreaded EXC_BAD_ACCESS.

Also, using malloc/free would probably be my first choice here, since you get to be very explicit about how and when the memory is allocated and freed. NSMutableData + autorelease isn't really buying you anything except some overhead, if you aren't using the object for anything else.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top