【问题标题】:Instruments says I'm leaking a string, but I can't find itInstruments 说我漏了一根弦,但我找不到
【发布时间】:2011-09-23 14:02:37
【问题描述】:

我使用 Instruments 中的泄漏工具测试代码,但泄漏工具似乎找不到泄漏。

在我的代码末尾,NSLog(@"str count:%d",[str retainCount]); 的输出是 3。为什么?我不覆盖dealloc。 [a.name retainCount] 只有一次 我只自动释放 str 一次。所以 str 不应该泄漏。

@interface DataMode : NSObject {

    NSString * name;
}

@property (retain) NSString * name;

- initWithName:(NSString * )name_;
@end


@implementation DataMode

@synthesize name;

- initWithName:(NSString * )name_
{
    if ([super init] != nil)
    {
        name = name_;
        return self;
    }
    return nil;
}

@end


- (void) pressed:(id)sender
{
    for( int i = 0;i<10000000;i++)
    {
        NSString * str = [NSString stringWithFormat:@"zhang"];
        DataMode * a = [[DataMode alloc] initWithName:str];
        NSLog(@"a0 count:%d",[a retainCount]);
        NSLog(@"name1 count:%d",[a.name retainCount]);
        NSLog(@"name1 count:%d",[a.name retainCount]);
        NSLog(@"a1 count:%d",[a retainCount]);
        [ a  release];
        NSLog(@"str count:%d",[str retainCount]);
        NSLog(@"str count:%d",[str retainCount]);
    }


}
@end

【问题讨论】:

  • 您在发布问题时遇到了什么麻烦?也许我们可以帮忙。
  • 另外,不鼓励调用-retainCount,并且在 NSStrings 上尤其无用。我相信很快就会有人来解释。
  • 附带说明,您应该在初始化方法中复制或至少保留分配给name ivar 的字符串对象。
  • 您在使用 ARC 吗?垃圾收集?手动内存管理?
  • retainCount 不会在 ARC 中编译,retainCount 在 GC 中有效返回 self.... 必须是手动的。

标签: iphone objective-c memory memory-leaks


【解决方案1】:

retainCount 没用。不要调用它。

它对于查找泄漏没有用处,因为有更好、更准确且误导性更少的工具可用。

您的代码存在几个问题(但泄漏不是其中之一):

  • NSString* 属性应该是copy

  • 您没有使用该属性设置init 中的字符串值,因此DataMode 实例不会保留其字符串。

  • 没有dealloc方法

至于保留计数;我很惊讶它是“3”。我希望它是 2bazillionsomething,因为它是一个常量字符串(常量字符串的 stringWithString: 只返回字符串)。由于您使用了 stringWithFormat:,因此常量字符串变成了非常量细绳。如果您使用了常量字符串或stringWithString:,那将是abazillionsomething(无符号-1...UINT_MAX...)。

无论如何,你有:

  • +1 stringWithString:
  • +1 拨打a.name
  • +1 拨打a.name

+3 总体。

如果 Instruments 声称存在泄漏,请发布屏幕截图。

【讨论】:

  • 它不是一个常量字符串,因为 OP 使用了+stringWithFormat:……而且没有格式,呵呵。
  • 哦,笨蛋。正确的。 stringWithString: 就是这样做的。 stringWithFormat: 不会打扰(尽管可以)。
  • 我认为它应该有泄漏。工具找不到。因为 [a.name retainCount] add 1 ,但我不释放它。因此我不使用 ARC。
  • 我认为它应该有泄漏。工具找不到。因为 [a.name retainCount] add 1 ,但我不释放它。str的计数是3。我只自动释放它一次。因此我不使用 ARC。
【解决方案2】:

我将NSObject protocol reference 引用为-retainCount

这种方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能已经保留了一个对象以保存对它的引用,而同时自动释放池可能在一个对象上保存了任何数量的延迟释放,所以您不太可能从中获得有用的信息方法。

由于多种原因,保留计数可能为 3;如果您无法使用泄漏工具找到泄漏,则很可能您没有泄漏。不用担心保留计数的实际值。

如果您真的对为什么它是 3 感兴趣,请记住:

  • 您的 DataMode 对象 a 的引用可能会一直保留到最近的自动释放池耗尽为止
  • 您仍然在 str 变量中持有引用
  • NSString 类集群,除其他外,在内部做了一些 - 异常莫名其妙 - 缓存的东西,所以你可能会看到一些没有人可以解释的保留

【讨论】:

  • 几乎就在保留的来源...... DataMode 对象在自动释放池中的存在不会影响字符串的保留计数。
  • 代码混乱;鉴于其余代码的编写方式,DataMode 不会保留字符串。这是错误的。
【解决方案3】:

由于您使用便捷方法创建自动释放的str,因此您不会看到以这种方式使用保留计数的确定行为。

查看我对另一个问题的回复并将这些方法添加到DataMode,您应该会看到框架何时从自动释放池中释放您的对象。

Overriding release and retain in your class

【讨论】:

    猜你喜欢
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 2012-05-19
    • 2020-05-28
    • 2017-08-26
    • 2010-12-01
    • 2015-12-26
    相关资源
    最近更新 更多