【问题标题】:Objective - C - NSMutableAttributedString Leak目标 - C - NSMutableAttributedString 泄漏
【发布时间】:2011-10-25 01:08:33
【问题描述】:

我是 Obj-C 的新手,并且正在尝试一些东西。 我偶然发现了一个泄漏问题,想知道其背后的逻辑原因。

以下代码泄露

(textViewAttrStr is an instance variable of type NSMutableAttributedString)

-(void) init:(NSString*)str
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str];
[textViewAttrStr appendAttributedString:part1String];
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"];
[textViewAttrStr appendAttributedString:part2String];
[textViewAttrStr retain];

[part1String release];
[part2String release];

[pool drain];
}

-(void) dealloc
{
if(textViewAttrStr != nil)
{
    [textViewAttrStr release];
}

[super dealloc];
}

虽然下面的代码不会泄露

-(void) init:(NSString*)str
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str];
[tvas appendAttributedString:part1String];
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"];
[tvas appendAttributedString:part2String];

textViewAttrStr = tvas;
[textViewAttrStr retain];

[part1String release];
[part2String release];
[tvas release];

[pool drain];
}

-(void) dealloc
{
if(textViewAttrStr != nil)
{
    [textViewAttrStr release];
}

[super dealloc];
}

谁能解释一下原因?

【问题讨论】:

  • 感谢大家的快速回复。这使内存管理对我来说更容易一些。 :)

标签: objective-c cocoa memory-leaks nsmutablestring


【解决方案1】:

第一个示例的问题是额外的保留。您需要删除它,因为当您使用 [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 创建 textViewAttrStr 时它已经被保留了

//Remove this line in the first example
[textViewAttrStr retain];

【讨论】:

    【解决方案2】:

    第一个例子:

    textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
    //...
    [textViewAttrStr retain];
    

    第二个例子

    NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
    //...
    [tvas release];
    

    您现在应该看到,在您的第一个示例中,您已经分配/初始化并保留了它,哎呀。

    第二个例子,你正确分配/初始化然后释放。

    简单的规则:如果你分配/初始化或复制或保留,你必须在某个时候释放。如果是类变量,则在dealloc中释放,否则在离开作用域前释放。

    【讨论】:

      【解决方案3】:

      您的第二个示例表明您不明白为什么在第一个示例中存在泄漏,因此您选择进行试验,这似乎是一种可以理解的方法。

      在您的第二个示例中, textViewAttrStr 和 tavs 基本相同。它们都是内存中同一个对象的引用(或指针)。

      所以,当你这样做时:

      textViewAttrStr = tvas;
      [textViewAttrStr retain];
      //...
      [tvas release];
      

      对该对象的保留调用与对该对象的释放调用相平衡。这几乎是无所作为。在此处删除保留和释放调用提供了相同的功能。删除这些后,您的对象的引用计数为 1,因为您调用了 alloc,并且当 dealloc 命中时,它将达到 0 并被释放。

      现在,在您的第一个示例中,您的对象被分配(引用计数为 1),然后被保留(引用计数为 2),当 dealloc 命中时,它将达到引用计数 1 而您的对象不会被释放并因此泄漏。所以这里的解决办法就是去掉retain调用。

      顺便说一句,在向对象发送释放消息之前检查对象是否不是 nil 是不必要的,因为向 nil 发送消息什么都不做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 2012-07-08
        • 2012-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多