I want to implement a stack that works quite like a circular buffer.
void** pp = malloc(sizeof(id) * 100);
pp[index] = someObject;
// later on somewhere:
MyObject* myObj = (MyObject*)pp[index];
Is this correct? Does this approach work with ARC?
No, it's not safe as you have written it.
Since you've told the compiler that pp
contains only raw pointers (void**
), the stored object reference doesn't have a corresponding retain count. This means that the pp
array isn't keeping its objects alive, and they're subject to deallocation if there happen to be no other references.
You can get this one step better by declaring pp
as MyObject**
instead of void**
. In that case, storing an object pointer in the array will store a strong reference. IOW, the object's retain count will be incremented when you store a reference in the array, keeping the object alive even if all other references disappear.
However, it's still not that simple:
-
When you store a reference in the array (including the first time after you allocated the array), the previous reference at that index will get released. Initially, there are no guarantees about the contents of the malloc'ed block, so you would need to explicitly set all of its bytes to 0, essentially initializing everything in the array to
nil
. Or, usecalloc
instead ofmalloc
. -
When you lose or free your pointer to the malloc'ed array, you would need to make sure that you caused every reference in the array to decrement its retain count, since you're also discarding all the references in the array. You could do this by setting every element of the array (when typed
MyObject**
) to nil.
Now, there's already API that handles all of these details for you: it's NSArray
. Use NSArray
for a simple, reliable solution.