Re: Garbage collector vs variable lifetime
Re: Garbage collector vs variable lifetime
- Subject: Re: Garbage collector vs variable lifetime
- From: "Michael Ash" <email@hidden>
- Date: Sat, 7 Jun 2008 22:10:44 -0400
On Sat, Jun 7, 2008 at 6:37 PM, Hamish Allan <email@hidden> wrote:
> On Sat, Jun 7, 2008 at 7:35 PM, Michael Ash <email@hidden> wrote:
>
>> This is pretty nitpicky. If it's in scope but you don't use it, then
>> it doesn't matter. Kind of like a Zen koan: if an object is collected
>> in the forest but nobody is pointing to it anymore, does it make a
>> sound?
>
> :)
>
> I'm just arguing that it makes it more straightforward if the GC
> behaves deterministically according to the code you wrote, rather than
> what the optimising compiler re-wrote for you.
If you don't like undefined behavior, then C-based languages are a
poor choice. If you don't like nondeterministic object lifetimes, then
garbage collection is a poor choice.
The compiler and garbage collector both do their jobs. They keep the
object around as long as it is referenced, after which it becomes a
candidate for collection. The trouble is just that where it stops
being referenced and where you think it should stop being referenced
are not the same place.
>>>> How would it be less straightforward? If it returned collected memory
>>>> then everything will Just Work for the common case of using the
>>>> pointer on the stack. You would also have the additional convenience
>>>> of being able to safely store the returned pointer in a __strong heap
>>>> variable, something which you simply cannot do under non-GC rules at
>>>> all. Looks like there are only improvements to me, where is the
>>>> problem?
>>>
>>> I agree with you that if it returned collected memory, it would be
>>> more powerful than under retain/release/autorelease. But power and
>>> straightforwardness do not always go hand in hand ;)
>>
>> Hmm, you didn't answer my question though. Where exactly is the
>> problem? For the case where the old-style rules also work, it would be
>> precisely as straightforward. (In case your objection is with the
>> __strong qualifier, note that you would not need that for a local
>> variable, only for instance variables.)
>
> Where is the problem with having NSData return collected memory? I
> have no problem with that, I just don't think it solves the whole
> problem.
The problem is that NSData sometimes wraps memory which is abnormal.
For example, +[NSData dataWithContentsOfMappedFile:] most likely uses
mmap (or the mach equivalent) under the hood. This then requires the
use of munmap (or the mach equivalent) to free that memory. The Cocoa
GC currently doesn't support such custom allocation and deallocation
schemes, so NSData can't use collected memory in the general case. It
could use it for *most* cases, but that would just make this problem
occur even more inconsistently.
> Now it's your turn -- where is the problem with the compiler marking
> references you have *semantically* placed on the stack as strong,
> whether or not they really end up on the stack after optimisation?
The problem is that this proposal doesn't make any sense given the
architecture of the Cocoa GC. The GC considers the stack plus
registers of each thread to be one big blob which it then scans for
anything that looks like a pointer. There's no way to mark anything as
being "strong", because the collector considers everything on the
stack to be strong. Even if this were to be resolved it still wouldn't
help because the problem isn't that the data pointer isn't strong, the
problem is that the data pointer *goes away*. No amount of annotation
will fix that; you have to change the compiler to keep object pointers
on the stack through the end of the current scope, and if you make
that change then the annotation is unnecessary anyway.
>> I disagree. Since the programmer cannot possibly know the state of the
>> call stack in any other way than by knowing that the compiler must
>> keep references to objects right up to the point where those objects
>> are no longer used, he must not make any assumption as to the lifetime
>> of those objects beyond that point.
>
> But who is to say the compiler won't make optimisations which alter
> when the object is last referenced? (See my reply to Peter for a code
> example.)
As Chris Hanson pointed out, the compiler cannot move function or
method calls without changing the underlying semantics of the code, so
you're guaranteed to be safe by doing a [data self] or equivalent at
the end of the loop. You can also, of course, use CFRetain/CFRelease
to more explicitly manage its lifetime.
If you're doubtful about this, consider what would happen in a boring
non-collected environment if the compiler were allowed to move this
stuff around. A [obj release] or free(ptr) could be moved to before
code which accesses the object or pointer, which would of course
result in disaster.
Aside from the NSData design problem, the fundamental problems here
are the expectations. The first being the expectation that scope
equals stack presence. This is not true in the general case, and
simply can't be relied on. Your reading of the GC docs as implying
that scanning the stack implies following scoping rules in the
language is IMO faulty, as the stack is an implementation detail which
is only loosely related to scope. You said that it must be this way
because scope is the only thing that the programmer can actually see.
This is not actually so; another thing the programmer can see, and
which lines up perfectly with guaranteed stack presence, is variable
use. Once a variable stops being used, you have no guarantee that it
remains on the stack. If it does so, it is because you are getting
lucky, not because it's supposed to work that way.
The second problem is that of expecting release builds to behave like
debug builds. It's the nature of C that it's relatively easy to
encounter nasal demons*, and it's the nature of C compilers that said
demons happen a lot more frequently in release builds. However, this
does *not* mean that the release build is displaying faulty behavior.
In many cases, including this one, the release build is actually
exposing faulty code, whereas the debug build is hiding it by working
as the programmer wants it to despite the code not actually being
correct.
* http://catb.org/jargon/html/N/nasal-demons.html
Mike
_______________________________________________
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