[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GNUstep and valgrind

From: David Chisnall
Subject: Re: GNUstep and valgrind
Date: Tue, 20 Mar 2018 08:21:34 +0000

On 20 Mar 2018, at 07:48, H. Nikolaus Schaller <address@hidden> wrote:
> Well, not really. Refer to the section on Garbage collection in the 
> nsautoreleasepool documentation.
> It mainly seems to say:
> 1. for GC you don't need an ARP

Not entirely true.  In GC mode, autorelease pools are hints that a lot of 
short-lived dead objects have been created.  The -drain method provides a hint 
to the GC that it should run an incremental collection.  Its intended use is 
the same in all cases (RR, GC, and ARC): to indicate that a lot of short-lived 
objects have been created, most of which are now probably dead.

> 2. if you write a framework that should work with GC *and* ARP you should use 
> it
> 3. using -drain is a hint for the GC, contrary to -release

In both GC and ARC mode, -release is not permitted (or, in hybrid GC mode, is 
silently ignored).  The -drain method can be called at any point.  In ARC mode, 
you are not allowed to explicitly create ARP objects.

@autoreleasepool works in ARC and non-ARC mode (with compilers from the last 
decade) and is intended to force autorelease pools to respect lexical scoping.  
This decision was made because it is incredibly hard to reason about object 
lifetimes if you don’t preserve this invariant and most code that I have seen 
that didn’t is buggy.  In non-ARC mode, it creates an autorelease pool on entry 
to the block and destroys it on exit.  

In ARC mode, there is one autorelease list per thread and the annotation simply 
provides markers in this list.  When you exit the scope, all autoreleased 
objects further along the list are released.  This makes creating autorelease 
pools very cheap (a single function call that returns a pointer into an 
existing data structure, via a TLS access - no memory allocation).  The 
interface is changed from create / drain to push/pop, to make this more 
explicit.  If you are using RR mode with GNUstep on an ARC-enabled runtime, the 
ARP simply calls push on creation and pop on destruction / drain.

It also means that you can’t do silly things like autorelease an autorelease 
pool (I’ve seen code once that did this intentionally - conditionally putting 
the current autorelease pool into the parent pool so that they’d be released 
together).  In ARC mode, the compiler is responsible for transferring ownership 
of live objects between autorelease pools, in RR mode you are responsible for 
doing this yourself.

In 2018, there is really no excuse for not using ARC.  GNUstep / clang has 
supported it since 2011.  Manual RR mode will generate slower (and bigger) code 
that is much more likely to contain memory management bugs.  In ARC mode, it is 
always safe (and cheap) to stick in an extra @autoreleasepool directive around 
a block where you think a lot of objects are going to be created (for example, 
in a loop body) and the compiler will retain and autorelease objects that need 
to be live after the end of the loop.  In RR mode it requires careful reasoning 
about object ownership.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]