2

我有点像可可新手,我根本无法弄清楚为什么我在使用此代码的 Instruments 中的泄漏图中会出现峰值。这似乎是一个小泄漏(即 16 字节,泄漏的对象是“Generalblock-16”;这是唯一泄漏的对象,并表示 Self 100%),无论我选择仅 1 个文件还是12,000 个文件。我已经双击了仪器的扩展详细信息视图中显示的堆栈跟踪的每一行,它不会引导我进入代码中的任何行。

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

YV

PS:如果我的代码没有问题(我对此表示怀疑)并且泄漏只是一个错误或与我的代码无关的东西,那么按原样使用此代码是否安全?它会给我的应用程序带来不稳定或崩溃或类似的情况吗?

@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
4

7 回答 7

4

尝试在您的代码上运行 CLang 静态分析器

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

并修复它指出的每一件事。我从来没有见过它指出错误的地方,尽管有时我确信它是错误的。它特别适合查找泄漏和其他与参考相关的问题。

于 2009-07-11T03:26:38.327 回答
1

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

NSMutableDictionary * theDict;

NSMutableDictionary * theDict = nil;

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

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

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

于 2009-07-11T03:38:56.460 回答
1

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

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

调用“autorelease”会将对象添加到自动释放池中,一旦您的函数执行完毕,它将自动释放。它很方便——因为你不必记得调用 release。无论哪种方式都可以在这里工作 - 不过。

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

编辑:

这种大小的泄漏不应导致您的应用程序出现任何不稳定。当您寻找内存泄漏时,您需要注意:

  1. 涉及大块内存(NSData 或 NSImage 对象等)的泄漏
  2. 循环内部或重复调用的函数中的泄漏(这将很重要)。

即使在 iPhone 上(您的应用程序获得大约 28MB 的 RAM,最大值),16 字节或 32 字节的一些泄漏也不是什么大问题。一般来说,Instruments 会在应用程序启动时报告一些泄漏——这些都不是什么大问题。您只是想确保在您的应用程序运行时不会泄漏越来越多的内存 - 因为认真的用户可能会继续运行您的应用程序,直到所有可用内存都被泄漏。操作系统不会重用泄漏的内存,因为它认为您的应用仍在使用它——因此最终您将无法为新对象分配内存。

希望有帮助!

于 2009-07-11T03:30:56.583 回答
1

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

2) 而不是调用:

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

您应该可以简单地调用:

theDict = [NSMutableDictionary dictionary];

它们本质上是一样的。

于 2009-08-03T06:53:52.103 回答
0

大家好!非常感谢您的及时答复!

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

如果导致泄漏的不是我的代码,并且-正如您所提到的-只是系统中的某些东西,您认为尽管存在轻微泄漏,使用我的代码是否安全?还是会导致我的应用程序不稳定或崩溃?

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

再次感谢你的帮助!

于 2009-07-11T03:50:34.643 回答
0

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

  1. NSOpenPanel *openThePanel = [NSOpenPanel openPanel];
  2. [openThePanel setAllowsMultipleSelection:YES];
  3. if([openThePanel runModal] == NSOKButton)
  4. NSArray *allTheFiles = [openThePanel filenames];

尝试注释掉每一个 - 当您注释掉 openPanel 调用或询问文件名时模拟数据,并假装为 if 语句调用 runModal。

一次将它们注释掉并测试泄漏,然后您可以查看哪条线路负责并跟进...

于 2009-07-11T04:21:38.027 回答
0

泄漏检测器之王valgrind移植到 OS X。 valgrind将找到您的内存泄漏并告诉您分配站点的确切位置,甚至更重要的是,分配对象时调用堆栈上的内容。 valgrind是救生员!

于 2009-07-11T04:22:04.283 回答