Skip navigation.
 
mlAccessing buffers in NSData/NSMutableData under garbage collection
FROM : Rick Hoge
DATE : Mon Feb 18 23:21:14 2008

I have a question about recommended coding style under GC, which I'll 
preface with some background.

I've been trying to learn about garbage collection under Leopard by 
turning it on in some older apps and watching how they fail.  As 
stated in the GC docs, you probably don't want to switch to GC in a 
mature application that was developed under the older memory 
management scheme.  However studying the effects of GC in old apps 
was certainly helpful in planning better design patterns for future 
projects.

One of the patterns that breaks badly is the following type of thing:

float *myPointer = [[NSMutableData dataWithLength:size*sizeof(float)] 
mutableBytes];

This was convenient as a lazy (if perhaps misguided) way to replace 
malloc with something that I knew I could use until the end of the 
current event loop, and which would then be freed automatically.  Note 
that aside from the lazy, autoreleased malloc replacement, there are 
many other cases where I use NSMutableDatas (e.g. where the data will 
be used as an instance variable for one or more objects)

It's quite possible that this was a bad thing to do under the old 
style of memory management, but it's fatal under GC.  As far as the 
collector is concerned, the inner NSMutableData object is no longer 
reachable at later points during execution (whatever that means after 
compiler optimization).  If you use myPointer later, it's quite likely 
that it will point to freed memory.  Using

__strong float *myPointer = [[NSMutableData 
dataWithLength:size*sizeof(float)] mutableBytes];

does not seem to be a solution, since (at least as I understand it) 
the collector cares about references specifically to the NSMutableData 
object and a strong pointer to an internal storage buffer (not an 
object) won't prevent the object and its associated bytes from being 
reclaimed (since the buffer can not "reach" the object).

Ok, fine.  I can live with that.  Now, however, I need to decide how 
to replace the following kind of thing:

//////////////////////////////////////////////////////////////////////  Start
  code snippet //////////////////////////////////////////

NSMutableData *myData = [NSMutableData 
dataWithLength:size*sizeof(float)];

float *myPointer = [myData mutableBytes]; // Don't think __strong 
would make a difference here

int ix;
for (ix=0; ix<size; ix++) myPointer[ix] = mysillyfunction(ix); // This 
causes an intermittent crash

// Insert Thousands of lines of code here

BOOL someFlag = YES;
if (someFlag) {
   // Collector will probably have nuked myData a long time ago... 
usually crashes by here
   float answer = myPointer[3];
}

//////////////////////////////////////////////////////////////////////  End
  code snippet //////////////////////////////////////////

So this leads to the following questions:

- am I correct in understanding that it is a bad idea to *ever* copy 
the pointer returned by -mutableBytes (or any other pointer-returning 
method) to a variable for future use, since this assignment can't be 
followed by the collector, which might at any time reclaim the parent 
object?  (use of __strong not withstanding?)

- so is the preferred if not mandatory alternative to *always* use the 
-mutableBytes method in any line of code that needs to access the data 
of an NSMutableData object?  I can do this, but it seems to make the 
code less readable (not the end of the world - clearly it's better 
than crashing).

- should I expect a significant performance cost to the overhead of 
the method call inside of a tight loop?  e.g.  for

(ix=0:ix<size;ix++) *((float*)[myData mutableBytes] + ix) = 
somefunc(ix*3.0);
vs.
(ix=0:ix<size;ix++) myPointer[ix] = somefunc(ix*3.0);

- would I have been better to just use __strong *float myPointer = 
NSAllocateCollectible(size*sizeof(float),0)?  My instinct (under pre-
GC) has been to use NSData or NSMutableData for memory buffers that 
might end up being assigned as instance variables to other objects. 
Under the GC world, what are the advantages of NSData/NSMutableData 
vs. a buffer returned by NSAllocateCollectible()?  I have encountered 
situations where NSMutableData is unable to allocate very large memory 
buffers (e.g. 700MB) when GC is turned on (the same line of code is 
works with GC off).  NSAllocateCollectible() does not seem hindered by 
these limitations for large blocks of memory under GC.

Thanks in advance for any suggestions,

Rick

Related mailsAuthorDate
mlAccessing buffers in NSData/NSMutableData under garbage collection Rick Hoge Feb 18, 23:21
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Adam P Jenkins Feb 19, 06:00
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection mmalc crawford Feb 19, 06:07
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Adam P Jenkins Feb 19, 06:19
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Adam P Jenkins Feb 19, 06:23
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Chris Suter Feb 19, 07:24
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Alastair Houghton Feb 19, 12:48
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Adam P Jenkins Feb 19, 15:26
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Alastair Houghton Feb 19, 15:46
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Quincey Morris Feb 19, 19:36
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Chris Suter Feb 19, 19:38
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Michael Ash Feb 19, 20:03
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Alastair Houghton Feb 19, 20:28
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Quincey Morris Feb 19, 22:12
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Chris Suter Feb 19, 23:42
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Quincey Morris Feb 20, 00:35
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Michael Ash Feb 20, 00:44
mlRe: Accessing buffers in NSData/NSMutableData under garbage collection Chris Suter Feb 20, 00:59