Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

objective-c memory management--how long is object guaranteed to exist?

I have ARC code of the following form:

NSMutableData* someData = [NSMutableData dataWithLength:123]; ...

CTRunGetGlyphs(run, CGRangeMake(0, 0), someData.mutableBytes); ...

const CGGlyph *glyphs = [someData mutableBytes]; ...

...followed by code that reads memory from glyphs but does nothing with someData, which isn't referenced anymore. Note that CGGlyph is not an object type but an unsigned integer.

Do I have to worry that the memory in someData might get freed before I am done with glyphs (which is actually just pointing insidesomeData)?

All this code is WITHIN the same scope (i.e., a single selector), and glyphs and someData both fall out of scope at the same time.

PS In an earlier draft of this question I referred to 'garbage collection', which didn't really apply to my project. That's why some answers below give it equal treatment with what happens under ARC.

like image 398
Merk Avatar asked Dec 20 '22 16:12

Merk


2 Answers

You are potentially in trouble whether you use GC or, as others have recommended instead, ARC. What you are dealing with is an internal pointer which is not considered an owning reference in either GC or ARC in general - unless the implementation has special-cased NSData. Without that owning reference either GC or ARC might remove the object. The problem you face is peculiar to internal pointers.

As you describe your situation the safest thing to do is to hang onto the real reference. You could do this by assigning the NSData reference to either an instance variable or a static (method local if you wish) variable and then assigning nil to that variable when you've done with the internal pointer. In the case of static be careful about concurrency!

In practice your code will probably work in both GC and ARC, probably more likely in ARC, but either could conceivably bite you especially as compilers change. For the cost of one variable declaration and one extra assignment you avoid the problem, cheap insurance.

[See this discussion as an example of short lifetime under ARC.]

like image 133
CRD Avatar answered Feb 02 '23 00:02

CRD


Under actual, real garbage collection that code is potentially a problem. Objects may be released as soon as there is no longer any reference to them and the compiler may discard the reference at any time if you never use it again. For optimisation purposes scope is just a way of putting an upper limit on that sort of thing, not a way of dictating it absolutely.

You can use NSAllocateCollectable to attach lifecycle calculation to C primitive pointers, though it's messy and slightly convoluted.

Garbage collection was never implemented in iOS and is now deprecated on the Mac (as referenced at the very bottom of this FAQ), in both cases in favour of automatic reference counting (ARC). ARC adds retains and releases where it can see that they're implicitly needed. Sadly it can perform some neat tricks that weren't previously possible, such as retrieving objects from the autorelease pool if they've been used as return results. So that has the same net effect as the garbage collection approach — the object may be released at any point after the final reference to it vanishes.

A workaround would be to create a class like:

@interface PFDoNothing

+ (void)doNothingWith:(id)object;

@end

Which is implemented to do nothing. Post your autoreleased object to it after you've finished using the internal memory. Objective-C's dynamic dispatch means that it isn't safe for the compiler to optimise the call away — it has no way of knowing you (or the KVO mechanisms or whatever other actor) haven't done something like a method swizzle at runtime.

EDIT: NSData being a special case because it offers direct C-level access to object-held memory, it's not difficult to find explicit discussions of the GC situation at least. See this thread on Cocoabuilder for a pretty good one though the same caveat as above applies, i.e. garbage collection is deprecated and automatic reference counting acts differently.

like image 35
Tommy Avatar answered Feb 01 '23 23:02

Tommy