Re: Garbage collector vs variable lifetime
Re: Garbage collector vs variable lifetime
- Subject: Re: Garbage collector vs variable lifetime
- From: Bill Bumgarner <email@hidden>
- Date: Fri, 06 Jun 2008 15:48:53 -0700
On Jun 6, 2008, at 3:23 PM, Quincey Morris wrote:
In a GC-only app, I frequently use a pattern along these lines:
NSData* data = <get it from somewhere>;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
The "release" (but not the "debug") build of the app crashes
(EXC_INVALID_ACCESS) at the 'bytes [i]' reference in one such piece
of code. AFAICT, the crash happens because 'data' has been garbage
collected out of existence during the loop. [The "somewhere" that
'data' came from in this case was a __weak instance variable that is
0 at the time of the crash but wasn't earlier; thread 2's stack
trace shows the garbage collector finalizing a NSMutableData (which
is what 'data' actually is) at the time of the crash.]
Apparently, compiler optimization has decided to shorten the
lifetime of 'data' to *not* encompass the loop, and I was unlucky
enough to have the garbage collector run in a separate thread during
the loop execution.
Surely it ought to be regarded as a horrible compilation bug for the
lifetime of a variable to be shortened like this, since the lifetime
clearly has side effects (i.e. maintenance of a GC pointer)?
I tried adding "volatile" to the 'data' declaration, but that didn't
change anything. I tried adding a simple 'data;' statement after the
loop, but that got optimized away and the variable lifetime got
shortened as in the original code. Adding another 'count = [data
length];' after the loop did prevent the crash, because it
apparently wasn't optimized away.
It seems to me that the consequence of this compiler defect is that
it's not safe in general to use NSData in GC apps. At least, it's
not safe to assume that a stack reference is sufficient to keep a
NSData object alive.
Anyone got a less drastic perspective on this situation?
The garbage collector does not currently interpret inner pointers as
something that can keep an encapsulating object alive. Thus, the
behavior is undefined and that it changes between debug and release
builds -- between optimization levels of the compiler -- is neither
surprising nor considered to be a bug.
With that said, it sure is darned annoying and, yes, the actual
development / debugging experience on this front is definitely
something that could be improved. Whether that improves by solving
the inner pointer issue or by improving the above to fail more
predictably and gracefully, only time will tell.
In any case, you need to make sure that <data> stays alive throughout
the entire lifespan of the bytes pointer. This is no different than
in non-GC. If <data> were released sometime before the for loop were
done, a similar crash would occur.
b.bum
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
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