IOS:发布NSString不能按预期工作

我用NSString发现了一个奇怪的行为。 我试图运行下面的代码,并注意到这一点。

NSString *str = [[NSString alloc] initwithstring : @"hello"]; [str release]; NSLog(@" Print the value : %@", str); 

在这里,在第三行应用程序应该崩溃,因为我们正在访问一个被释放的对象。 但它正在打印str的值。 这不是崩溃。 但与NSArray我观察到不同的行为。

 NSArray *array = [[NSArray alloc] initwithobjects : @"1", @"2", nil]; [array release]; NSLog(@"Print : %@", [array objectatindex : 0]); NSLog(@"Print : %@", [array objectatindex : 0]); 

该代码有两个用于NSArray的NSLog语句。 这里在释放第一个NSLog执行后,它是打印值。 但是,当第二个NSLog执行,应用程序崩溃。 应用程序崩溃是可以接受的,因为访问的数组已被释放 但是当第一个NSLog被执行时它会崩溃。 不是第二个。

帮助我的这种行为。 在这些情况下,释放如何工作。

谢谢吉腾

第一个示例不会崩溃,因为string文字从不释放。 代码是真的:

 NSString *str = @"hello"; [str release]; 

人们在内存pipe理上被string文字烧毁,错误地使用==来比较它们而不是isEqualToString: 编译器会进行一些优化,导致误导结果。

更新

下面的代码certificate了我的观点:

  NSString *literal = @"foo"; NSString *second = [NSString stringWithString:literal]; NSString *third = [NSString stringWithString:@"foo"]; // <-- this gives a compiler warning for being redundant NSLog(@"literal = %p", literal); NSLog(@"second = %p", second); NSLog(@"third = %p", third); 

这段代码给出了以下输出:

2013-02-28 22:03:35.663 SelCast [85617:11303] literal = 0x359c
2013-02-28 22:03:35.666 SelCast [85617:11303] second = 0x359c
2013-02-28 22:03:35.668 SelCast [85617:11303] third = 0x359c

注意,所有三个variables指向相同的内存。

你的第二个例子在第二个NSLog崩溃,因为在第一个日志中, array所在的内存没有被重用,但是第一个日志在堆上导致足够的活动,导致内存被别的东西占用。 然后,当您尝试再次访问它时,您会遇到崩溃。

每当一个对象被释放并且其内存被标记为空闲时,将会有一段时间该内存仍然存储该对象剩下的内容。 在这段时间内,您仍然可以调用这些对象的方法等等,而不会崩溃。 这一次是非常短的,如果你运行了很多的线程,可能不足以让你的方法调用。很显然,不要依赖这个实现细节的任何行为。

正如其他人所说,关于你的第一个问题, NSString文字不会被释放。 对于其他一些基础类( NSNumber ),这也是正确的,但也是一个实现细节。 如果您需要在内存pipe理上进行实验,请使用NSObject实例,因为它不会显示exception行为。

在对象上发送release消息时,实际上不会从内存中删除该对象。 发布消息只是将引用计数减1 。 如果引用计数为零,则该对象被标记为空闲。 然后系统将其从内存中移除。 在这个释放之前,你可以访问你的对象。 即使release对象,对象指针仍指向对象,除非将指针指定为nil

第一个示例不会崩溃,因为string文字从不释放。 第二个完全取决于发布和保留计数器。

阅读这篇文章。 它包含你的查询简短而又甜蜜的解释

你应该阅读这个苹果指南

你似乎认为release应该立即破坏对象。 我不认为这是语言的保证。 release意味着什么:我已经完成使用这个对象,我保证不再使用它。 从这一点开始,系统决定何时实际释放内存。

除此之外,您所看到的任何行为都没有定义,并且可能会从Objective C运行时的一个版本更改为下一个版本。

也就是说,其他答案表明差异是string文字和内存的重新使用是正确的,但假设行为将永远是这样的可能是一个错误。