无法弄清楚内存泄漏的来源

时间:2009-07-11 03:18:04

标签: objective-c cocoa memory-leaks instruments

我有点像可可新手,我简直无法弄清楚为什么我在这个代码的仪器泄漏图中出现了高峰。它似乎是一个小泄漏(即16字节和泄漏对象是“Generalblock-16”;这是唯一泄漏的对象,并说自我100%)并且它似乎保持这个大小,无论我是否只选择1个文件或12,000个文件。我双击了Instruments的Extended Detail视图中显示的Stack Trace的每一行,它不会引导我进入代码中的任何一行。

提前感谢您提供的任何帮助。

Y.V。

P.S。:如果我的代码没有任何问题(我怀疑)并且泄漏只是一个错误或与我的代码无关的东西,那么使用这个代码是否安全?它是否会导致我的应用程序不稳定或发生崩溃或类似的事情?

@implementation AppController

-(IBAction)openTheOpenPanel:(id)sender
{
    NSOpenPanel *openThePanel = [NSOpenPanel openPanel];
    [openThePanel setAllowsMultipleSelection:YES];

    if([openThePanel runModal] == NSOKButton)
    {
        NSArray *allTheFiles = [openThePanel filenames];    

        int theNumberOfFiles = [allTheFiles count];

        int i;

        NSMutableDictionary * theDict;
        theDict = [[NSMutableDictionary alloc] init];

        for (i=0; i < theNumberOfFiles; i++) {
            NSString *thisFile = [allTheFiles objectAtIndex:i];
            NSString *theFileNum = [NSString stringWithFormat:@"%i", i];

            [theDict setObject:thisFile forKey:theFileNum]; 
        }

        [theDict writeToFile:@"/tmp/test_file.txt" atomically:YES];

        [theDict release];
    }
}

@end

7 个答案:

答案 0 :(得分:4)

尝试在代码上运行CLang Static Analyzer

http://clang-analyzer.llvm.org/

并修复它指出的每一件事。我从来没有看到它指出一些错误的东西,即使有时我确信它是。它特别擅长发现泄漏和其他参考相关问题。

答案 1 :(得分:1)

您的代码看起来不错!你所展示的内容没有任何内存泄漏。如果你愿意,你可以像这样声明theDict:

theDict = [[[NSMutableDictionary alloc] init] autorelease];

调用“autorelease”会将对象添加到自动释放池中,并且一旦执行了该函数,它将自动释放。它很方便 - 因为你不必记得打电话给释放。无论哪种方式都可以在这里工作 - 但是。

每次调用此函数时,您的应用程序是否会泄漏,或者只是第一次?如果Instruments没有向您显示泄漏源自的一行代码,则可能只是系统中的某些内容。根据我的经验,从随机系统问题中经常发生一些小泄漏。

编辑:

此尺寸的泄漏不应导致您的应用程序出现任何不稳定现象。当您在寻找内存泄漏时,您需要注意:

  1. 泄漏涉及大块的 内存(NSData或NSImage对象等)
  2. 在循环内部或函数中泄漏 反复调用(这将加起来 重要)。
  3. 即使在iPhone上(你的应用程序获得大约28MB的RAM,最大值),一些16字节或32字节的泄漏也不是什么大问题。通常,仪器会在应用程序启动时报告一些泄漏 - 这些并不是一个大问题。您只是想确保在应用程序运行时没有泄漏越来越多的内存 - 因为严重的用户可能会继续运行您的应用程序,直到所有可用内存泄露。操作系统不会重复使用泄露的内存,因为它认为您的应用程序仍在使用它 - 所以最终您将无法为新对象分配内存。

    希望有所帮助!

答案 2 :(得分:1)

不是它会解决任何问题,但我建议不断改变

NSMutableDictionary * theDict;

NSMutableDictionary * theDict = nil;

否则theDict可能会有一些奇怪的 - 未知 - 内存地址,直到你分配/初始化它为止。如果你这样做:

NSMutableDictionary * theDict;
if (theDict) {
  // condition is true
}

即使您尚未自己初始化theDict,也会满足条件。

答案 3 :(得分:1)

1)检查以确保在可执行环境变量中没有将NSZombieEnabled设置为YES。

2)而不是打电话:

theDict = [[[NSMutableDictionary alloc] init] autorelease];

您应该可以简单地致电:

theDict = [NSMutableDictionary dictionary];

它们本质上是一样的。

答案 4 :(得分:0)

嘿伙计们!非常感谢你的快速回答!

本,非常感谢你的建议。像你建议的那样自动释放字典实际上是我对代码的第一种方法,但是它泄露了,所以我将我的代码从自动释放改为手动分配和释放,不幸的是,它泄漏的数量相同(相同的对象和泄漏量)。

如果不是我的代码导致泄漏的原因 - 你提到的 - 只是系统中的东西,你认为尽管存在轻微的泄漏,使用我的代码是安全的吗?还是会导致我的应用程序出现不稳定或崩溃?

我已经按照它的方式进行了广泛的测试,到目前为止,它没有在我的任何测试中显示出任何问题(我只注意到使用仪器存在泄漏)。

再次感谢您的帮助!

答案 5 :(得分:0)

在该代码中,您有四条可能导致泄漏的行:

  1. NSOpenPanel *openThePanel = [NSOpenPanel openPanel];
  2. [openThePanel setAllowsMultipleSelection:YES];
  3. if([openThePanel runModal] == NSOKButton)
  4. NSArray *allTheFiles = [openThePanel filenames];
  5. 尝试注释掉每一个 - 当您注释掉openPanel调用或询问文件名时模拟数据,并为if语句调用runModal。

    一次一个地评论它们并测试泄漏,然后你可以看到哪条线负责并跟进它......

答案 6 :(得分:0)

检漏之王<valgrindported to OS X。{{3}}。 valgrind将发现您的内存泄漏,并告诉您分配站点的确切位置,更重要的是,分配对象时调用堆栈上的内容。 valgrind是一个生命之辈!