【发布时间】:2010-01-19 17:00:10
【问题描述】:
我一直在拼命想弄清楚我是如何在垃圾收集的 Cocoa 应用程序中发生内存泄漏的。 (Activity Monitor 中的内存使用量会不断增长,使用 GC Monitor 工具运行应用程序也会显示不断增长的图表。)
我最终将其缩小到代码中的单一模式。数据被加载到 NSData 中,然后由 C 库解析(数据的字节和长度被传递给它)。 C 库有回调,它会触发并返回子字符串的起始指针和长度(以避免内部复制)。但是,出于我的目的,我需要将它们变成 NSStrings 并保留一段时间。我通过使用 NSString 的 initWithBytes:length:encoding: 方法来做到这一点。我以为这会复制字节并且 NSString 会适当地管理它,但是出了点问题,因为这会像疯了一样泄漏。
此代码会“泄漏”或以某种方式欺骗垃圾收集器:
- (void)meh
{
NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"holmes" ofType:@"txt"]];
const int substrLength = 80;
for (const char *substr = [data bytes]; substr-(const char *)[data bytes] < [data length]; substr += substrLength) {
NSString *cocoaString = [[NSString alloc] initWithBytes:substr length:substrLength encoding:NSUTF8StringEncoding];
[cocoaString length];
}
}
我可以将其放入计时器中,然后通过 Activity Monitor 和 GC Monitor 工具观察内存使用量的上升和上升。 (holmes.txt 为 594KB)
这不是世界上最好的代码,但它说明了问题所在。 (我正在运行 10.6,该项目的目标是 10.5 - 如果重要的话)。我阅读了垃圾收集文档并注意到了许多可能的陷阱,但我认为我没有做任何明显违反这里规则的事情。不过问也无妨。谢谢!
这是一张不断增长的对象图的图片:
【问题讨论】:
-
我在运行它时看不到任何泄漏,运行几分钟后它的内存使用量在 7.5MB 和 9MB 之间徘徊。
-
这很奇怪。我在 10.6.2。我内置了调试和发布。在所有情况下,我都看到了不断增长的记忆。 wtf...
-
我现在让其他人在 10.5 上运行它,他报告说它似乎也没有增长。我需要让其他 10.6+ 的人尝试一下。
-
使用“泄漏”仪器运行我没有泄漏,使用“对象分配”给出了 Bryan 观察到的行为
-
Leaks 在雪豹上的 GC 下运行良好,顺便说一句。但是,它往往不会显示垃圾但尚未收集的东西。这纯粹是一个与阈值相关的问题。