对象被释放后仍然给出了他们的价值观。 ARC未标记(表示关闭)
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//test of retain and copy
NSString *s1 = [[NSString alloc] initWithString:@"String1"];
NSString *s2 = [s1 copy];
[s1 release];
[s1 release];
[s2 release];
if(s1!=nil)
{
NSLog(@"11111");
NSArray *array = [[NSArray alloc] initWithObjects:@"1",@"2",@"3", nil];
[array release];
NSLog(@"S1 - %@ \n S2 - %@ \n Array - %@",s1,s2,array);
}
}
===输出===
2012-12-14 15:04:01.165 testMM [940:207] 11111 2012-12-14 15:04:01.168 testMM [940:207] S1 - String1 S2 - String1 数组 - S1 - String1 S2 - String1 数组 -
答案 0 :(得分:0)
首先,访问已解除分配的对象是未定义的行为。它可以访问看起来像原始对象的内容(如果它使用的内存没有被覆盖),或者它可能访问另一个对象(后来碰巧在那里分配),或者它可能访问随机垃圾(根本不是对象) ),或者它可能会崩溃或做其他奇怪的事情。没有办法判断一个对象是否被释放,除非你打开僵尸来捕获对已释放对象的调用。
不仅如此,即使您释放了所有保留对象,也无法保证何时取消分配对象。当一个对象的保留计数变为0时,该对象被释放。但即使您分配并释放了一个对象,也可能有一些API可以保留然后自动释放它。例如你分配然后立即释放数组,但有可能在initWithObjects:
中它保留并自动释放自身(保留和自动释放对象永远不会是错误的),尽管在init
中这是不可能的。
特别是在这种情况下,对于字符串,@"String1"
是一个文字字符串,存在于静态内存中,而retain
和release
上的内存管理操作则不执行任何操作。 NSString
,当您基于常量字符串创建新字符串时,只返回该常量字符串;并且常量字符串上的copy
也返回该常量字符串。所以基本上s1
和s2
都指向永远存在的静态内存中的字符串文字。 release
对他们没有任何影响。 (但从内存管理规则的角度来看仍然是不正确的。)
array
已分配并发布。这里可能发生的事情(我在这里猜测,由于上述原因)是数组确实被释放,但是由于打印时间很短,因此该部分内存没有被覆盖。同样,这是未定义的行为。