• 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
Re: Accessing buffers in NSData/NSMutableData under garbage collection
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Accessing buffers in NSData/NSMutableData under garbage collection


  • Subject: Re: Accessing buffers in NSData/NSMutableData under garbage collection
  • From: Rick Hoge <email@hidden>
  • Date: Tue, 19 Feb 2008 09:37:08 -0500


Thanks for the helpful replies -

From the replies and further experimentation I think I now understand that:

1) The code fragment in my original post *will* break if optimization is turned on, but not if it is off:

-(IBAction)danglePointer:(id)sender {
int size = 1e6;
NSMutableData *testData = [NSMutableData dataWithLength:sizeof(float)*size];
float *testPointer = (float*)[testData mutableBytes]; // Note that __strong makes no difference here
[[NSGarbageCollector defaultCollector] collectExhaustively];
sleep(1); // If there is no delay, I was not able to get a crash (in 20-30 trials)
BOOL flag = YES;
if (flag) {
testPointer[0] = 3; // If optimization is turned on, the code crashes at this line every time
NSLog(@"testPointer = %f",testPointer[0]);
}
}


Also, with optimization turned on, the above code only crashes if I insert the delay between the -collectExhaustively call. Without the delay, I can happily call this method over and over again (with optimization on) without getting a crash. Maybe this is a reflection of the fact that the collector runs in another thread, and needs time to complete the collection. Note also that it's clearly not just scope rules that determine when collection can take place, since testData is still in scope at the crashing line of code. Note also that using __strong in front of the pointer declaration makes no difference, since the collector cares about references to the object and not to its internal structures. The above snippet (with delay) better represents my real apps, in which there may be a lot of processing work done between instantiation of the NSMutableData and later use of the pointer. In my haste to put together a tiny test case, I built and ran it in "Debug" mode the first time (optimizations off), which appears to be why I couldn't get the crash. Of course replacing the two lines including testPointer[0] with

    *((float*)[testData mutableBytes] + 0) = 3.0;
    NSLog(@"testPointer = %f",*((float*)[testData mutableBytes] + 0));

runs fine under optimization.


2) NSAllocateCollectible() is probably a more appropriate choice in the above example. I have tested a number of scenarios running the Object Allocation template in Instruments to test apps with large blocks allocated in this way, and the memory footprint of the app appears to be controlled quite effectively under GC.



3) You can declare pointer instance variables using the __strong qualifier and these can point to blocks allocated with NSAllocateCollectible(). The memory will live as long as the object, and is freed when the object is reclaimed (sorry if this is obvious, but I had to test it to be sure myself). I was able to create a GC doc-based apps in which the docs 'own' 100MB memory buffers allocated in the above way - these have the appropriate lifetime and are reclaimed at the appropriate time.



Having realized the above points, this gets back to part of my original question regarding programming style (rather than correctness) under GC. On this note I'm still trying to figure out:


1) What potential pitfalls might arise if I start using NSAllocateCollectible to create buffers where I used to use NSData objects? The obvious differences, which may not matter depending on the app, seem to be:

- can't put the buffer into a collection (NSArray, NSDictionary, etc.) as easily as an NSData/NSMutableData
- less obvious how KVC should work
(before, if I updated an NSData or NSMutableData object, I'd use a setXXX method and KVC would just work.
with a buffer, I could probably use -willChangeValueForKey:/- didChangeValueForKey: so this is probably not a huge deal)
- lose the ease of doing a -copy and -mutableCopy to replicate the memory chunk (not much more work with a buffer, though)
- lose the serialization and archiving methods of NSData/ NSMutableData



2) As mentioned above, there may be situations where objects want to be notified when the data contained in a buffer allocated with NSAllocateCollectible() (and referenced by a pointer instance variable in another object) changes. One simple approach would be to make sure code that modifies the memory is wrapped with -willChangeValueForKey:/- didChangeValueForKey: calls. This will almost surely work, but I wonder if this is considered good style (since I may not really be changing the pointer value, just values in the memory that it points to). Any comments on this or suggestions for better ways would be welcome.


Thanks again,

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: Alastair Houghton <email@hidden>
References: 
 >Re: Accessing buffers in NSData/NSMutableData under garbage collection (From: Gordon Apple <email@hidden>)
 >Re: Accessing buffers in NSData/NSMutableData under garbage collection (From: Rick Hoge <email@hidden>)
 >Re: Accessing buffers in NSData/NSMutableData under garbage collection (From: Mika Ryynänen <email@hidden>)

  • Prev by Date: Re: Accessing buffers in NSData/NSMutableData under garbage collection
  • Next by Date: Re: Accessing buffers in NSData/NSMutableData under garbage collection
  • Previous by thread: Re: Accessing buffers in NSData/NSMutableData under garbage collection
  • Next by thread: Re: Accessing buffers in NSData/NSMutableData under garbage collection
  • Index(es):
    • Date
    • Thread