使用自动释放池@property复制和手动内存管理



我有一个类,它复制了一个NSString并打印了它的保留计数和地址。

@interface TestStringPointer : NSObject
@property (copy) NSString *stringTest;
- (void)printPointer;
@end
@implementation TestStringPointer
- (void)printPointer {
  NSLog(@"PrintPointer:%pn RetainCount:%lu", _stringTest, [_stringTest retainCount]);
}
@end

在我的主函数中,我对String的指针进行了一些调查,结果遇到了一个问题。

int main(int argc, const char * argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  TestStringPointer *test = [[TestStringPointer alloc] init];
  NSString *myString = [NSString stringWithUTF8String:"Hello World"];
  NSLog(@"MyString: %p n RetainCount:%lu", myString, [myString retainCount]);
  [test setStringTest:myString];
  [test printPointer];
  [myString release];
  [pool drain];
  while (1) {
    [test printPointer];
  }
  return 0;
}

当我调试应用程序时,它在while循环中第三次崩溃(循环的次数各不相同)。我知道复制不会发生是因为字符串不可变。在它主要发布后,我本以为它会回到1。
1) 如果一个对象没有自动释放,它还会影响自动释放池吗
2) 最大保留计数不是可以防止对象在池中被耗尽吗?还是可以将其标记为删除
3) 副本不应该在某个时候介入,并在被删除之前真正制作了一份副本吗?

StringPointerTest〔2253:303〕我的字符串:0x100100f60保留计数:1
StringPointerTest〔2253:303〕打印指针:0x100100f60保留计数:2
StringPointerTest〔2253:303〕打印指针:0x100100f60保留数量:1152921504606846975
StringPointerTest〔2253:303〕打印指针:0x100100f60保留计数:1152921504606846975

如果我修改main并删除池

int main(int argc, const char * argv[])
{
  TestStringPointer *test = [[TestStringPointer alloc] init];
  NSString *myString = [NSString stringWithUTF8String:"Hello World"];
  NSLog(@"MyString: %p n RetainCount:%lu", myString, [myString retainCount]);
  [test setStringTest:myString];
  [test printPointer];
  [myString release];
  while (1) {
    [test printPointer];
  }
  return 0;
}

一切都好。。。永远

StringPointerTest[423:303]我的字符串:0x10010a670保留计数:1
StringPointerTest[423:303]打印指针:0x10010a670保留计数:2
StringPointerTest[423:303]打印指针:0x10010a670保留计数:1

错误在于发布myString。这是错误的,因为stringWithUTF8String返回了一个自动释放的字符串(请记住,每个方法都有自动释放的版本:静态方法,非自动释放版本:init或initWithSomething:)。因此,当自动释放池耗尽时,myString保留计数变为零,对象被释放(也许稍后,您不知道确切的时间,它在第三次循环迭代时崩溃的事实是偶然的)。

因此,您可以通过调用alloc+initWithUTF8String:而不是stringWithUTF8String:来解决问题。事实上,你看到了令人难以置信的高保留计数,这与内存已经被释放并可能再次写入的事实相矛盾,在对象真正被释放之前,这只是一个陷阱,你不再拥有对象了。

相关内容

  • 没有找到相关文章

最新更新