对象被释放了,它们仍然给出了它们的值。 ARC 未标记(表示关闭)

Posted

技术标签:

【中文标题】对象被释放了,它们仍然给出了它们的值。 ARC 未标记(表示关闭)【英文标题】:Objects were released still they gave their values . ARC were Not mark (means Off) 【发布时间】:2012-12-14 09:57:34 【问题描述】:

对象被释放了,但它们仍然给出了它们的值。 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 测试MM[940:207] 11111 2012-12-14 15:04:01.168 testMM[940:207] S1 - String1 S2 - 字符串 1 数组 - S1 - String1 S2 - 字符串 1 数组 -

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

以上是关于对象被释放了,它们仍然给出了它们的值。 ARC 未标记(表示关闭)的主要内容,如果未能解决你的问题,请参考以下文章

10.7 上的 ARC 迁移工具给出错误:删除未使用的“自动释放”消息是不安全的

for 循环中的强类对象未保留在 ARC 中

ARC 引入了哪些新的类型限定符?

About Memory Analysis

【OC梳理】循环引用及解决

git repo 中的文件都被删除和未跟踪,但它们仍然存在。这怎么可能?