Objective-C 2.0的内存pipe理

我是Objective-C的初学者。 我正在通过编写简单的命令行代码研究Objective-C中的内存pipe理。

我的环境在下面。

  • Mac OS X Mountain Lion。
  • Xcode4.5

我在下面写了一个代码。

test.m

1 #import <Foundation/Foundation.h> 2 #import <stdio.h> 3 4 @interface A : NSObject 5 -(void)myprint; 6 @end 7 8 @implementation A 9 -(void)dealloc { 10 printf("dealloc!!\n"); 11 [super dealloc]; 12 } 13 14 -(void)myprint { 15 printf("myprint!!\n"); 16 } 17 @end 18 19 int main(void) { 20 21 id obj1 = [[[NSObject alloc] init] autorelease]; 22 id obj2 = [[A alloc] init]; 23 24 [obj2 release]; 25 [obj2 myprint]; 26 27 return 0; 28 } 

我使用下面的命令构build了这个代码(使用无ARC选项构build)

 clang -g -Wall -o main test.m -fno-objc-arc -framework Foundation 

构build成功,没有任何警告消息。 结果如下。

 dealloc!! myprint!! 

我有两个关于这个结果的问题。

第一个问题是关于自动释放方法。 我认为这段代码会引发一个运行时错误,因为autorelease方法被调用时没有NSAutoreleasePool实例。 为什么这段代码不会产生运行时错误?

第二个问题是关于dealloc方法。 调用dealloc方法后,obj2响应myprint方法。 为什么在调用dealloc方法之后obj2响应myprint方法?

谢谢。

第一个问题是关于自动释放方法。 我认为这段代码会引发一个运行时错误,因为autorelease方法被调用时没有NSAutoreleasePool实例。 为什么这段代码不会产生运行时错误?

没有autorelease池,因此,我有点惊讶,你没有看到在运行时没有到位警告 。 这不会是一个错误,只是一个运行时警告,发生泄漏。

奇。 我看到了同样的行为。 我会问。

第二个问题是关于dealloc方法。 调用dealloc方法后,obj2响应myprint方法。 为什么在调用dealloc方法之后obj2响应myprint方法?

未定义的行为。 obj2已被释放,但释放并不意味着内存已被清除。

如果你打开Malloc Scribble(在释放时在内存上涂写),你会看到一个预期的崩溃:

 env MallocScribble=1 ./main dealloc!! Segmentation fault: 11 

更好的是,如果你打开僵尸检测:

 env NSZombieEnabled=YES ./main dealloc!! 2012-12-06 08:10:14.580 main[80114:f07] *** -[A myprint]: message sent to deallocated instance 0x7f9b7ac09dd0 Trace/BPT trap: 5 

我相信一个autorelease池是自动创build的,但我可能是错误的那一个。 至于第二部分,我的理解是释放告诉一个对象停止被保留,所以不能保证在释放消息之后的任何时候仍然存在,但是这可能会持续一段时间,直到这块内存被用于别的东西。 本质上,你是幸运的,如果你再次运行你的代码,你可能不会每次都有obj2响应myprint。

我试了一下,你可以看到发生了什么事情:

正如你可以看到没有autorelease池…泄漏显示在debugging器。

在这里输入图像说明

编辑:

我做了研究,并且知道,释放正在工作,但系统正在花时间释放,直到下一个打印语句被调用。 您可以检查以下代码:

 A *obj2 = [[A alloc] init]; NSLog(@"1rc=%ld",[obj2 retainCount]); [obj2 release]; for (long i=0; i<1000000; i++) { for (long j=0; j<10000; j++) { ; } } [obj2 myprint]; for (long i=0; i<1000000; i++) { for (long j=0; j<10; j++) { ; } } NSLog(@"myprint again"); [obj2 myprint];