物品被释放后仍然给出了它们的价值。 ARC没有标记(意味着关闭)

时间:2012-12-14 09:57:35

标签: objective-c copy release retain

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

1 个答案:

答案 0 :(得分:0)

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

不仅如此,即使您释放了所有保留对象,也无法保证何时取消分配对象。当一个对象的保留计数变为0时,该对象被释放。但即使您分配并释放了一个对象,也可能有一些API可以保留然后自动释放它。例如你分配然后立即释放数组,但有可能在initWithObjects:中它保留并自动释放自身(保留和自动释放对象永远不会是错误的),尽管在init中这是不可能的。

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

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