0

对象被释放了,它们仍然给出了它们的值。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 数组 -

4

1 回答 1

0

首先,访问已释放的对象是未定义的行为。它可能会访问看起来像原始对象的东西(如果它使用的内存没有被覆盖),或者它可能会访问另一个对象(碰巧稍后被分配),或者它可能会访问随机垃圾(根本不是一个对象) ),否则它可能会崩溃或做其他奇怪的事情。没有办法判断一个对象是否被释放,除非你在启动僵尸的情况下运行以捕获对释放对象的调用。

不仅如此,即使在释放对象上的所有保留后,也无法保证何时释放对象。一个对象在其保留计数变为 0 时被释放。但即使您分配并释放了一个对象,也有可能某些 API 可能已保留然后自动释放它。例如,您分配然后立即释放数组,但它可能会在initWithObjects:其中保留和自动释放自身(保留和自动释放对象永远不会不正确),尽管在init.

特别是在这种情况下,对于字符串来说,@"String1"是一个存在于静态内存和内存管理操作中的字面量字符串,它喜欢retain并且release不做任何事情。NSString,当您基于常量字符串创建新字符串时,只需返回该常量字符串;并且copy在常量字符串上也返回该常量字符串。所以基本上s1s2两者都指向静态内存中永远存在的字符串文字。release对他们没有影响。(但从内存管理规则的角度来看仍然是不正确的。)

array被分配和释放。这里可能发生的事情(我猜这里,由于上述原因)是数组确实被释放了,但是那部分内存在你打印它时并没有被覆盖,因为它的时间太短了。同样,这是未定义的行为。

于 2012-12-14T22:31:10.527 回答