• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Accessing buffers in NSData/NSMutableData under garbage collection
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Accessing buffers in NSData/NSMutableData under garbage collection


  • Subject: Accessing buffers in NSData/NSMutableData under garbage collection
  • From: Rick Hoge <email@hidden>
  • Date: Mon, 18 Feb 2008 17:21:14 -0500


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








_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: Accessing buffers in NSData/NSMutableData under garbage collection
      • From: Adam P Jenkins <email@hidden>
  • Prev by Date: NSTask output only after termination of NSTask
  • Next by Date: Re: NSTask output only after termination of NSTask
  • Previous by thread: Re: NSTask output only after termination of NSTask
  • Next by thread: Re: Accessing buffers in NSData/NSMutableData under garbage collection
  • Index(es):
    • Date
    • Thread