Garbage Collection API

This article summarizes the classes, methods, and functions associated with garbage collection.

Foundation

Foundation provides several classes to help support design patterns associated with garbage collection, and the behavior of several methods in existing classes is changed when running under garbage collection.

NSObject

NSObject adds the finalize method; other methods listed below are ignored completely or have changed semantics when used in a garbage collected environment.

+allocWithZone:(NSZone *)zone

The zone argument is ignored.

- (id)autorelease

This method is a no-op.

-(void)dealloc

This method is a no-op.

-(void)finalize

Conceptually similar to the traditional dealloc—for more details, see Implementing a finalize Method.

- (oneway void)release

This method is a no-op.

- (id)retain

This method is a no-op.

- (NSUInteger)retainCount

The return value is undefined.

NSAutoreleasePool

NSAutoreleasePool adds the drain method.

-(void)drain

Triggers garbage collection if memory allocated since last collection is greater than the current threshold. (This method ultimately calls objc_collect_if_needed().)

NSGarbageCollector

NSGarbageCollector provides an object-oriented abstraction of the garbage collector. You use defaultCollector to return the collector (this returns nil in a reference-counted environment).

You can use disableCollectorForPointer: to ensure that memory at a given address will not be scanned—for example, to create new root objects. You balance this with enableCollectorForPointer:, which makes collectable memory that was previously marked as uncollectible.

Collection Classes

NSHashTable is a collection class like NSMutableSet but which (amongst other features) provides the ability to create weak references to its contents.

NSMapTable is a collection class like NSMutableDictionary but which (amongst other features) provides the ability to create weak references to its contents.

NSPointerArray is a collection class like NSArray but it can also hold NULL values, which can be inserted or extracted (and contribute to the object’s count). Also unlike traditional arrays, you can set the count of the array directly. Under Garbage Collection and using a zeroing weak memory configuration, NULL values appear when elements are collected. A pointer array uses an instance of NSPointerFunctions to define callout functions appropriate for managing a pointer reference held somewhere else.

NSValue

NSValue has a method to wrap a non-retained object, valueWithNonretainedObject:.

+(id)valueWithNonRetainedObject:(id)anObject

Creates a new NSValue object containing a weak reference to anObject. If anObject is garbage collected, the reference is set to nil.

NSThread

NSThread provides additional functionality for currentThread.

Foundation Functions

Various functions have been added.

void *NSAllocateCollectable(NSUInteger size, NSUInteger options)

Allocates size bytes of memory using the given option.

id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);

The zone parameter is ignored by NSAllocateObject in GC mode.

id NSMakeCollectable(CFTypeRef cf)

This function is a wrapper for CFMakeCollectable (see Core Foundation Functions), but its return type is id, avoiding the need to cast if you assign the value to a Cocoa object.

This function may be useful when returning Core Foundation objects in code that must support both garbage-collected and non-garbage-collected environments, as illustrated in the following example.

- (NSString *)description
{
    CFStringRef myCFString = CFStringCreate...(...);
    return [NSMakeCollectable(myCFString) autorelease];
}

Core Foundation

The behavior of several functions is different under garbage collection. The Core Foundation collection types (such as CFSet, CFMutableSet, CFDictionary, and CFArray) correctly support the standard “retaining” callbacks under GC in a way that allows cycles to be recovered, unlike non-GC behavior. Note also that NULL callbacks will weakly reference objects, but are not done with zeroing memory—you still need to remove objects from the collection. If you need zeroing weak object behavior, use NSHashTable or NSMapTable instead.

CFMutableArray

Changed semantics when creating with NULL arguments.

CFArrayCreateMutable(NULL, 0, NULL)

References contents weakly, does not zero. You must remove objects from the array.

CFMutableDictionary

Changed semantics when creating with NULL arguments.

CFDictionaryCreateMutable(NULL, 0, NULL, NULL)

References contents weakly, does not zero. You must remove objects from the dictionary.

Core Foundation Functions

New and changed functions.

CFTypeRef CFMakeCollectable(CFTypeRef anObject)

Checks that anObject is a Core Foundation object allocated in the scanned memory zone and, in a garbage collected environment, releases it. This function is a no-op in a reference-counted environment.

void CFRelease(CFTypeRef anObject)

Decrements the retain count for anObject. If anObject was allocated in a garbage collected zone, then if its retain count is reduced to zero it is not actually deallocated until next collection. If anObject was allocated in a malloc zone, then if its retain count is reduced to zero it is deallocated immediately. Thus for GC objects, CFRelease() no longer has immediate side-effects.

Language Support

Features and functions.

__strong

Specifies a reference that is visible to (followed by) the garbage collector (see How the Garbage Collector Works).

__strong modifies an instance variable or struct field declaration to inform the compiler to unconditionally issue a write-barrier to write to memory. __strong is implicitly part of any declaration of an Objective-C object reference type. You must use it explicitly if you need to use Core Foundation types, void *, or other non-object references (__strong modifies pointer assignments, not scalar assignments).

__strong essentially modifies all levels of indirection of a pointer to use write-barriers, except when the final indirection produces a non-pointer l-value. When you declare a variable, you can put __strong on either side of the *; in the following example, all the variable declarations are equivalent:

@interface MyClass {
    __strong int *ptr1;
    int * __strong ptr2;
    int __strong * ptr3;
}
__weak

Specifies a reference that is not visible to (followed by) the garbage collector (see How the Garbage Collector Works).

__weak informs the compiler to use a zeroing weak reference for a variable. All writes are done using a weak write-barrier, and all reads use a weak read-barrier. This allows you to reference a variable without preventing the variable from being garbage collected.

Weak references are set to zero (nil) if the destination is collected. If an object is collected, any weak instance variables are cleared before being finalized. Thus, in a finalize method, you can guarantee that any __weak instance variables have been set to nil.

Runtime

The runtime provides a number of functions to support different aspects of garbage collection, and an environment variable you can use to check whether GC is on or off for a process.

objc_allocate_object(cls, extra)

Allocates a new object.

id objc_msgSend(id theReceiver, SEL theSelector, ...)

Ignores these selectors: retain, release, autorelease, retainCount, dealloc. This is faster than messaging nil.

void objc_collect_if_needed(int options)

Triggers garbage collection if memory allocated since last collection is greater than the current threshold. Pass OBJC_GENERATIONAL to run generational collection.

This function must only be called from the main thread.

void objc_clear_stack(unsigned long options)

This function may be useful if you write your own event loop type mechanisms or code not using run loops—you need to clear the stack or risk unnecessarily extending the lifetime of objects.

Any uninitialized local variables will hold whatever values happen to be on the stack from previous function calls. Those values may be pointers to old objects which, while you don't consider the objects to still be live, the garbage collector will still see a reference to them on the stack and not collect them because of it. For example, if a function has a local variable which is a char array of MAX_PATH length, and you read a line and fill it with only a dozen characters, everything past the end of the dozen characters is left over from previous function calls and may be interpreted by the collector as pointers to objects.

OBJC_PRINT_GC

When debugging, you can perform a runtime check by setting the environment variable OBJC_PRINT_GC=YES. This prints the GC state of each Objective-C image, and whether GC is on or off for the process.