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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to