Wrong Retain Count

Discussion in 'Mac Programming' started by Mac Player, May 17, 2008.

  1. Mac Player macrumors regular

    Joined:
    Jan 19, 2006
    #1
    So here is the code

    Code:
    int main (int argc, const char * argv[]) {
    
    	NSNumber* newNumber;
    	int i;
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    	
    	for (i = 0; i < 40; i++) {
    		newNumber = [[NSNumber alloc] initWithInt:(i * 3)];
    		NSLog(@"%d\n", [newNumber retainCount]);
    	}
        [pool drain];
        return 0;
    }
    and here is the result:

    Code:
    2008-05-18 00:51:11.287 Lottery[845:10b] 2
    2008-05-18 00:51:11.289 Lottery[845:10b] 2
    2008-05-18 00:51:11.290 Lottery[845:10b] 2
    2008-05-18 00:51:11.290 Lottery[845:10b] 2
    2008-05-18 00:51:11.291 Lottery[845:10b] 2
    2008-05-18 00:51:11.291 Lottery[845:10b] 1
    2008-05-18 00:51:11.291 Lottery[845:10b] 1
    2008-05-18 00:51:11.292 Lottery[845:10b] 1
    2008-05-18 00:51:11.292 Lottery[845:10b] 1
    ...
    Why do the first 4 objects have a retain count of 2?

    TIA

    Edit: I just found out that some NSNumbers are cached.
     
  2. HiRez macrumors 603

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #2
    Yes, I noticed that before and I think that's correct. The number is retained once for yourself, and then I think the runtime slaps another retain on it for its own cacheing purposes. As you can see it only does this for small numbers (looks like between 12 and 14). Drove me nuts when I was trying to figure out what was going on, it would be nice for Apple to document this (I haven't seen it yet).
     
  3. kpua macrumors 6502

    Joined:
    Jul 25, 2006
    #3
    They won't document it because it's an implementation detail. The minute something like this is documented, they're bound to it forever.
     
  4. HiRez macrumors 603

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #4
    That's true, but they don't have to be specific. I mean something more generic, along the lines of "* Retain counts for built-in objects may be different than expected due to internal optimization or other implementation details". They could put this note right into NSObject's -retainCount documentation. Just to let the developer know that something really screwy is not going on, because I wasted a lot of time trying to track down the source of that and it seems I'm not the only one. The fact that it only happens in the first dozen or so integers makes it particularly nasty when you first run across it while debugging because the behavior changes even among the same object type.
     
  5. Nutter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #5
    The solution is to never, ever use the -retainCount method. For anything. Seriously, I don't know why it's even a public method. The retain count of an object is in itself an implementation detail, and is not to be relied upon, even for debugging purposes.
     
  6. Krevnik macrumors 68030

    Krevnik

    Joined:
    Sep 8, 2003
    #6
    The behavior changes partially because it isn't the same object type in the back-end. NSNumber is backed by a different type depending on what sort of value it was initialized with. Boolean values are considered 'permanently cached' for example, and are of the NSCFBoolean type rather than the NSCFNumber type. Their retain counts are always high, and retain/release are no-ops on an NSCFBoolean.

    As the other poster has said, retainCount is pretty much worthless (especially if you are trying to find memory leaks). A better tool would be to actually run Instruments against your application and watch the object allocations.
     

Share This Page