Reputation: 883
#import <Foundation/Foundation.h>
int main (int argc, char const *argv[])
{
SampClass *obj=[[SampClass alloc] init];
[obj release];
NSLog(@"%i", [obj retainCount]);
return 0;
}
Why does this give retainCount of 1, when it should be 0
Upvotes: 2
Views: 420
Reputation: 29343
The object is being dealloced but once the object goes to retain count 0 any method calls are likely to return stale values.
If you compile and run on 32 bit, you will get an error (message retainCount sent to freed object=0x...).
I'm guessing the 64bit runtime (default compile option on Leopard) does not collect objects as aggressively as the 32 bit runtime so your call to retainCount does not cause an error.
To check that you object is indeed dealloced, implement dealloc for your SampClass:
- (void) dealloc
{
NSLog(@"Dealloc");
[super dealloc];
}
Later edit: As I suspected, the difference in behavior between 32 and 64 bit when calling a method on a released object is from the runtime and not undefined behavior.
In 32 bit, once a class is freed it's isa pointer is switched to a special class that allows intercepting messages to freed objects. This does not happen in 64 bit. Relevant source is objc-class.m:
#if !__OBJC2__
// only clobber isa for non-gc
anObject->isa = _objc_getFreedObjectClass ();
#endif
Upvotes: 0
Reputation: 162722
Do not call retainCount
.
Not even in debugging code. And especially not when you are trying to learn how Cocoa's memory management works.
The absolute retain count of an object is not something under your control. Often, the value will be quite unexpected. There may be any number of caches, static allocations (like constant NSStrings), or other internal implementation details within frameworks that make an object's retain count other than what you expect.
The retain count of objects should be thought of entirely in terms of deltas. If you cause the retain count to increase, you must decrease it somewhere if you want the object to be deallocated. Period. End of story.
Trying to think of retain counts in absolute terms will just lead to confusion and wasted hours.
The Cocoa Memory Management Guide explains this rather well.
Upvotes: 9
Reputation:
There's no question of what retainCount should be in your code, you shouldn't be calling it. Relying on the result of messaging a deallocated object is not a good idea. Here's what happens when I copy your code, and run it with one of the (numerous) retain-count-debugging features of the frameworks:
heimdall:~ leeg$ pbpaste | sed s/SampClass/NSObject/g > fubar.m
heimdall:~ leeg$ cc -o fubar -framework Foundation fubar.m
heimdall:~ leeg$ NSZombieEnabled=YES ./fubar
2010-01-07 13:40:10.477 fubar[871:903] *** -[NSObject retainCount]: message sent to deallocated instance 0x10010d8f0
Trace/BPT trap
Upvotes: 1
Reputation: 1674
Because the object has been deallocated before your NSLog call.
I assume that release is implemented something like the following:
if(retainCount==1) [self dealloc]; else retainCount--;
and you are accessing the deallocated object illegally.
Update: Found these questions whose answers should enlighten you further: here and here.
Upvotes: 0