Re: Transitioning to GC-supported
Re: Transitioning to GC-supported
- Subject: Re: Transitioning to GC-supported
- From: John Engelhart <email@hidden>
- Date: Mon, 26 Oct 2009 18:31:57 -0400
What follows is my $0.02, and is worth every penny you paid for it. :)
On Mon, Oct 26, 2009 at 9:45 AM, Dave Keck <email@hidden> wrote:
> I'm planning on systematically going through each of my source files and
> updating them to be GC-supported. I've been compiling a list of things to
> do
> and to look out for. So far, this is what I've got:
>
> 1. Apply workaround for interior pointers by '[containingObject self];' at
> the end of the method, to keep the containing object alive. It would be
> great if I had a list of every accessor method that returned an interior
> pointer - I figure I'll just make a fancy regex to search through the
> framework headers for anything returning a void *, char *, etc., but of
> course this won't catch everything. I fear the bugs caused by using
> interior
> pointers will be subtle and intermittent which is why I'd like to exert the
> effort to patch every instance in one fell swoop, ideally without having to
> re-read every line that I've written for this (somewhat large) project.
>
My advice? Don't bother. While I have definitely had problems with the
above, it is almost always when I'm stress testing things. Often, though
not always, this problem is a "race condition" bug at its heart, so if
you're not pushing things hard, you're not likely to ever see it manifest.
Second, having done exercises like this, you're almost certainly going to
do it wrong. You are trying to out-think the compiler, and it has a way of
making you very humble. Furthermore, this problem is almost exclusively due
to the use of the optimizer- simply turning off optimization causes 99% of
the reasons why you need to do this to go away.
And if you're really stuck on using the optimizer and making all these
changes, I still wouldn't do it unless you're willing to audit the assembly
code that comes out of the compiler. You'd be surprised at how often the
compiler will do something different than what you expected.
> 6. Search for every use of '&', and use objc_assign_global() and
> objc_assign_ivar() as necessary.
>
Hopefully you wont end up having to deal with these kinds of cases. When
you do, it's not always clear which objc_assign_*() function you need to
use. When you need to use objc_assign_global() is obvious in only the most
trivial case: when you're directly accessing / referencing a global
variable. Many times it can be ambiguous. Another caveat is weak pointers,
which have a whole different set of functions and one of those has to be
used to even read the __weak variable.
> 7. Search for all opaque pointer types (void *, uintptr_t) and scold them.
>
The problem isn't opaque pointer types. The C language has a number of
rules, all very meticulously and well thought out, for dealing with this
very issue. The problem is, at least IMHO, not enough through was given to
how GC __strong and __weak interact with those rules, the consequences of
those interactions, and how to deal with the problems of those interactions
cause. For example, assigning a NSString *stringPointer to a void
*voidPointer = stringPointer; should probably be at least a warning, if not
an error. Since the compiler accepts it without complaint or warning it's
often hard to tell that you've created a potential problem. :( This has
been a big source of hard to find GC bugs for me- where a GC qualifier was
"dropped" during handling at some point.
> 8. Test and maintain sanity.
>
> This is my first trip to GC-land, so it's sure to be a learning experience.
> Any tips or pitfalls to look out for would be greatly appreciated!
>
One problem I've had with GC is that when things do go wrong, things go
really wrong. I've found that tracking down a GC caused bug to be many,
many orders of magnitude more difficult than its manual memory management
counterpart. This is mostly due to the nature of GC- if you "got something
wrong", say missed an objc_assign() somewhere, it's often not a problem.
The timing often has to be just right- even though you missed the call,
something else may make a objc_assign call that happens to cover your
mistake just a few thousand instructions later. Or, more frequently, the
lifetime of an object is so short that it doesn't matter anyway- it's really
only a problem when the collector is actively collecting. All in all, it's
just a big bag of hurt.
_______________________________________________
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