views:

85

answers:

1

In an objective C project with GC enabled, I am allocating an array of variable size on the stack like this:

MaValue *myStack = alloca((sizeof(id) * someLength));

(The reason why I want to do this is not important:) Then, within a loop, I push and pop stuff on/from myStack. Some of the things I push onto the stack are new objects that are not referenced from anywhere else.

My gut feeling tells me, that the objective C garbage collector doesn't know about those pointers and therefore would collect the new (otherwise unreferenced) objects. Part of that believe comes from the thought, that the objective C GC isn't really conservative but "knows its pointers" (e.g., through a stack map).

However, in all my experiments (inserting [[NSGarbageCollector defaultCollector] collectExhaustively] calls) I didn't get those objects to be collected – which is good, but unexpected. So it seems, that the GC is scanning the whole stack and, for example, conservatively assumes an integer that happens to have the value of a valid pointer to really be a pointer.

Is that correct? Or am I missing something?

+2  A: 

It is behaving correctly.

While the collector scans the heap exactly [as much as possible] in that each class has a layout and only the slots that refer to objects or use __strong are scanned, the stack must be scanned conservatively. Every pointer sized and pointer aligned slot on the stack must be scanned for references.

Thus, your alloca() bumps the stack pointer down and the collector scans all of it. You should probably throw in an assert to make sure the alloca'd space is pointer aligned as the behavior is otherwise undefined.

Actually, you really shouldn't use alloca() at all. Even the man page says

The alloca() function is machine and compiler dependent; its use is discouraged.

Instead, use NSAllocateCollectable() to allocate a scanned chunk of heap space. Unless you are talking about many allocations vs. your other operations, the overhead should be minimal. Furthermore, you no longer run [nearly as great] a risk of exceeding the maximum stack size of a thread (which isn't large and changes depending on which thread you are running on and how it is allocated.

bbum