2008 08 12Managing C Memory with Cocoa, 2
void* malloc_autorelease(size_t size) { void* p = malloc(size); [NSData dataWithBytesNoCopy:p length:size freeWhenDone:YES]; return p; }
And allocate your temporary data with :
// Allocate element* myTempData = malloc_autorelease(sizeof(element)*elementCount); // And that's it ! Don't care about freeing, NSData will do it for usThanks to Jonathan Wight for the
dataWithBytesNoCopy:length:freeWhenDone:
tip.-[NSData dataWithBytesNoCopy:length:freeWhenDone] does not return void. It returns an NSData object that frees its buffer when it is dealloc'd. Since you throw away that NSData object, your implementation will never free the allocated buffer.
Whoops! You're right. Of course I go re-read your post after I submitted my comment. As long as there's an autorelease pool in scope, it will work. Sorry!
Great tip, but I'm puzzled by one thing: isn't dataWithBytesNoCopy:p length:size freeWhenDone:YES
equivalent to simply dataWithBytesNoCopy:p length:size
? Or is there some subtle point I'm missing?
@Russell I've gone back reading NSData's doc and indeed both are equivalent. I didn't know dataWithBytesNoCopy:length:
freed its pointer, its variant dataWithBytesNoCopy:length:freeWhenDone:
apparently exists to create an NSData
that will not free the pointer.
So dataWithBytesNoCopy:length:
will work just as well !
For more variations: http://borkware.com/quickies/single?id=385 and http://borkware.com/quickies/single?id=352 ...
Thanks Rainer !
I did Google 'malloc autorelease' before writing that post, without finding anything relevant. I need to level up my Google-fu …
This has the odd side effect of the malloc'd memory being deallocated when the nearest autorelease pool as opposed to an explicit free. Since you're not returning the NSData* there is no way to retain the value for use later.
If you're method returned an NSData, you could still get at the element
NSData* tempData = malloc_autorelease(sizeof(element) * elementCount);
element* myTempData = (element*) [tempData bytes];
[tempData retain];
...
[tempData release];
Not caring when the memory is released is exactly the point :)
The lifetime of malloc_autorelease
memory is the same as autoreleased objects like [NSURL URLWithString:…]
and serves the same purpose : use some data now and don't care when it's freed, thanks to dataWithBytesNoCopy
that will do it for us.
Now, I like this solution, because it's readable :)