Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
- Subject: Re: Use of Mac OS X 10.5 / Leopards Garbage Collection Considered Harmful
- From: Chris Hanson <email@hidden>
- Date: Mon, 4 Feb 2008 17:21:56 -0800
On Feb 4, 2008, at 4:14 PM, John Engelhart wrote:
However, through some unspecified logic, SOME pointers are elevated
to 'Points to live GC data'.
The logic isn't unspecified.
If a variable is of an object type or is of a pointer type with the
qualifier "__strong", it refers to something allocated -- and cleaned
up -- by the collector. Otherwise, it refers to something not
allocated by the collector.
I mean, seriously, can anyone conjure up a compelling reason why the
default behavior of a pointer is that it does not point to live data?
Yes. Distinguishing between pointers to collector-allocated objects
and non-collector-allocated objects ensures that the collector has far
less work to do and can do the work it has more efficiently, because
it can have more exact information about what portions of memory it
needs to check for strong references to objects.
It also goes a long way towards preventing false roots, which can help
keep down the working set of an application that uses garbage
collection.
Your choice of words makes me suspect that you consider an object
pointer, such as NSObject *, and a C pointer, ala void * or char *,
to be two distinctly different things.
They can be; when running under GC, an object is assumed to be
allocated by the collector. An arbitrary buffer is not. If you want
to use an arbitrary "non-object pointer" type variable to refer to
something that is allocated by the collector (e.g. a buffer returned
from NSAllocateCollectable) you need to mark that variable with the
__strong type qualifier so it gets the same treatment as an object
type variable.
Pointers are pointers, and knowing which ones to treat as 'special'
is non-trivial and easy to get wrong.
In Objective-C it is relatively straightforward to tell which pointer
type variables to treat as objects. You have pointers to objects
which you can send arbitrary messages to, and pointers to things that
aren't objects which you can't send arbitrary messages to. The
compiler itself has to be able to tell the difference between them to
generate correct code, warnings, and errors. The syntax therefore
really isn't that ambiguous: If there has been an @interface or
@class declaration for it, it's an instances of a class, otherwise
it's something else.
In practice for many developers this isn't a significant issue. I
don't recall having seen any Cocoa code which used "char *" to store
an object pointer, for example. There are few places in idiomatic
Cocoa where you might commonly use a "void *" to store an object
pointer, and in those situations it's straightforward (and correct
under non-GC as well) to introduce a CFRetain of the object before
storing into the "void *" and a CFRelease of the object after the
"void *" is no longer relevant. (Under GC, CFRetain effectively adds
an extra root while CFRelease removes one.)
One of the places I do this is in code that presents a sheet, because
it returns control to the main run loop. If I have to pass an object
as the "(void *)context" parameter to the sheet invocation, I CFRetain
it first. Then in the sheet's did-dismiss selector (if it has one) or
did-end selector (if there's no did-dismiss), I CFRelease the object.
This ensures that "the sheet" acts as a root for the object in case
it's transient and just being used to pass information around.
[gcConstTitle setTitle:"Hello, world!"];
[gcUTF8Title setTitle:[[NSString stringWithUTF8String:"Hello, world
\xC2\xA1"] UTF8String]];
[[NSGarbageCollector defaultCollector] collectExhaustively];
NSLog(@"GC test");
printf("gcConstTitle title: %p = '%s'\n", [gcConstTitle title],
[gcConstTitle title]);
printf("gcUTF8Title title: %p = '%s'\n", [gcUTF8Title title],
[gcUTF8Title title]);
If you build this example non-GC, and you replace
[[NSGarbageCollector defaultCollector] collectExhaustively];
with
[pool drain];
it would be just as incorrect. The object backing that UTF-8 string
is no longer live, therefore you can't trust that the UTF-8 string
itself is valid.
I appreciate that the design of the Objective-C garbage collector in
Mac OS X 10.5 is not what you might be used to -- especially in that
it *does* take advantage of the fact that you can treat variables
typed as "object" differently from variables typed as "non-object
pointer" in Objective-C -- but it really doesn't have the fundamental
or design flaws that you assert it does.
-- Chris
_______________________________________________
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