リファレンスカウンタが予想と違う挙動をするのですが、なにか?

#import <Foundation/NSObject.h>
#import <stdio.h>

int main()
{
    id obj = [NSObject alloc];
    printf("alloc: %d\n", [obj retainCount]);
    [obj init];
    printf("init: %d\n", [obj retainCount]);
    [obj retain];
    printf("retain: %d\n", [obj retainCount]);
    [obj retain];
    printf("retain: %d\n", [obj retainCount]);

    [obj release];
    printf("release: %d\n", [obj retainCount]);
    [obj release];
    printf("release: %d\n", [obj retainCount]);
    [obj release];
    printf("release: %d\n", [obj retainCount]);  // <= ココ

    return 0;
}

以上のソースをref_count_test.mとして保存してコンパイル後に走らせてみます。
すると、

$ cc ref_count_test.m -framework Foundation
ref_count_test.m: In function ‘main’:
ref_count_test.m:7: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
ref_count_test.m:9: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
ref_count_test.m:11: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
ref_count_test.m:14: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
ref_count_test.m:16: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
ref_count_test.m:18: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
ref_count_test.m:20: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
$ ./a.out 
alloc: 1
init: 1
retain: 2
retain: 3
release: 2
release: 1
release: 1
$ 

何事もなく終了。


詳解 Objective-C 2.0によると上記ソースの「ココ」としたところで、

objc: FREED(id): message retainCount sent to freed object=0xXXXXXX

という感じのエラーメッセージが出るとのことですが…
3度目のrelease後もリファレンスカウンタがデクリメントされていないようです。なぜだ!
ちなみに ここ からダウンロードしてきたサンプルコードでも同様な動作でした。むむむ…。


で、もう一度releaseするようにしてみるとエラー。なぜでしょう?よくわかりません><

#import <Foundation/NSObject.h>
#import <stdio.h>

int main()
{
    id obj = [NSObject alloc];
    printf("alloc: %d\n", [obj retainCount]);
    [obj init];
    printf("init: %d\n", [obj retainCount]);
    [obj retain];
    printf("retain: %d\n", [obj retainCount]);
    [obj retain];
    printf("retain: %d\n", [obj retainCount]);

    [obj release];
    printf("release: %d\n", [obj retainCount]);
    [obj release];
    printf("release: %d\n", [obj retainCount]);
    [obj release];
    printf("release: %d\n", [obj retainCount]);
    [obj release];

    return 0;
}
$ cc 1.m -framework Foundation
1.m: In function ‘main’:
1.m:7: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
1.m:9: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
1.m:11: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
1.m:14: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
1.m:16: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
1.m:18: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
1.m:18: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘NSUInteger’
$ ./a.out 
alloc: 1
init: 1
retain: 2
retain: 3
release: 2
release: 1
release: 1
a.out(3707) malloc: *** error for object 0x100108e40: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap
$