【问题标题】:Can't find leak in my code在我的代码中找不到泄漏
【发布时间】:2010-04-01 19:35:12
【问题描述】:

过去几个小时我一直在试图找出我的代码中的内存泄漏。这里是:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

expression = [expression stringByTrimmingCharactersInSet:
              [NSCharacterSet whitespaceAndNewlineCharacterSet]]; // expression is an NSString object.

NSArray *arguments = [NSArray arrayWithObjects:expression, [@"~/Desktop/file.txt" stringByExpandingTildeInPath], @"-n", @"--line-number", nil];
NSPipe *outPipe = [[NSPipe alloc] init];

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/grep"];
[task setArguments:arguments];
[task setStandardOutput:outPipe];
[outPipe release];

[task launch];

NSData *data = [[outPipe fileHandleForReading] readDataToEndOfFile];

[task waitUntilExit];
[task release];

NSString *string = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""];

int linesNum = 0;

NSMutableArray *possibleMatches = [[NSMutableArray alloc] init];

if ([string length] > 0) {

    NSArray *lines = [string componentsSeparatedByString:@"\n"];
    linesNum = [lines count];

    for (int i = 0; i < [lines count]; i++) {

        NSString *currentLine = [lines objectAtIndex:i];
        NSArray *values = [currentLine componentsSeparatedByString:@"\t"];

        if ([values count] == 20)
            [possibleMatches addObject:currentLine];
    }
}
[string release];
[pool release];

return [possibleMatches autorelease];

我尝试遵循 Cocoa 内存管理的一些基本规则,但不知何故似乎仍然存在泄漏,我相信这是一个正在泄漏的数组。如果 possibleMatches 很大,这很明显。您可以通过使用任何大文件作为“~/Desktop/file.txt”和表达式来尝试代码,当 grep-ing 时会产生很多结果。

我犯了什么错误?

感谢您的帮助!

--Ry

编辑:我刚刚使用 Clang 静态分析器来查找我的代码中的泄漏,但它没有找到任何泄漏。它只找到无效的初始化,但这些不能对我的泄漏负责......

【问题讨论】:

  • 旁白:当您不需要索引时,您应该使用快速枚举 (for (NSString *currentLine in lines))。它的代码更简洁,打字更少,而且可能更快。

标签: cocoa memory-management nsarray nstask


【解决方案1】:

这里:

NSString *string = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""];

您正在覆盖string 对象指针,而没有释放或自动释放原始字符串。不要在方法结束时释放string,而是:

NSString *string = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease];
string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""];

【讨论】:

  • 谢谢,但泄漏仍然存在。
  • leaks &lt;yourappname&gt; 告诉你什么?
  • 另外,如果你设置了MallocStackLogging 环境变量,你应该能够看到你的泄漏被分配到哪里的踪迹。
  • $ 泄漏提取器进程 8279:2685 个节点分配了 543 KB 进程 8279:1 次泄漏,总共泄漏了 128 个字节。泄漏:0x100212e70 size=128 区域:DefaultMallocZone_0x100010000 string '/Developer/Applications/Xcode.app/Contents/PlugIns/GDBMIDebugging.xcplugin/Contents/Resources/PBGDBIntrospectionSupport.A.dylib' 不太确定这是有用的输出。使用带有泄漏的仪器它没有找到任何东西。但这不可能是真的,因为在我的程序(实际上是一个大循环)中,每个被分配的对象也应该被释放,所以一定有某个地方泄漏......
  • 奇怪,这看起来不像你的泄漏。 :S(当然,我可能是错的。)
【解决方案2】:

解决方案的一个可能途径是使用 Instruments 的 Leaks 模板。通过将检查范围设置为在这段代码之前开始,然后查看在这段代码返回后哪些分配仍然有效,您可以看到泄漏了什么,然后查看泄漏的指针历史记录和相应的堆栈跟踪以准确查看发生了什么。

【讨论】:

    最近更新 更多