gpt4 book ai didi

cocoa - Cocoa 垃圾收集导致内存泄漏

转载 作者:行者123 更新时间:2023-12-03 16:10:13 27 4
gpt4 key购买 nike

我一直在用头撞墙,试图找出垃圾收集的 Cocoa 应用程序中如何发生内存泄漏。 (事件监视器中的内存使用量只会不断增长,并且使用 GC 监视器工具运行应用程序也会显示不断增长的图表。)

我最终将其范围缩小到代码中的单一模式。数据被加载到 NSData 中,然后由 C 库解析(数据的字节和长度被传递到其中)。 C 库具有会触发并返回子字符串起始指针和长度的回调(以避免内部复制)。然而,出于我的目的,我需要将它们转换为 NSString 并保留它们一段时间。我通过使用 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 - 如果这很重要的话)。我阅读了垃圾收集文档并注意到了许多可能的陷阱,但我认为我没有做任何明显违反这里规则的事情。不过,问一下也没什么坏处。谢谢!

Project zip

这是一张不断增长的对象图的图片:

alt text

最佳答案

这是一个不幸的边缘情况。请提交一个错误(http://bugreport.apple.com/)并附上您优秀的最小示例。

问题有两个;

  • 主事件循环未运行,因此收集器不会通过 MEL 事件触发。这使得收集器仅执行基于阈值的正常背景收集。

  • 数据将从文件读取的数据存储到从 malloc 区域分配的 malloc 缓冲区中。因此,GC 占用的分配(NSData 对象本身)确实很小,但指向的东西非常大(malloc 分配)。最终结果是未达到收集器的阈值并且不进行收集。显然,改进这种行为是我们所希望的,但这是一个难题。

这是一个非常容易在微基准测试中或单独重现的错误。实际上,通常发生的事情足够多,这个问题就不会发生。但是,在某些情况下,它可能确实会出现问题。

将代码更改为此,收集器将收集数据对象。请注意,您不应该经常使用collectExhaustively——它确实会消耗CPU。

- (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];
}
[data self];
[[NSGarbageCollector defaultCollector] collectExhaustively];
}

[data self] 在最后一次引用数据对象后使数据对象保持事件状态。

关于cocoa - Cocoa 垃圾收集导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2095272/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com