没有游泳池释放的物体 - 只是泄漏?

时间:2010-01-30 13:39:46

标签: objective-c

没有游泳池的物品释放 - 只是漏水?
这个内存泄漏了吗? 我怎么能避免这个?

3 个答案:

答案 0 :(得分:2)

该对象未被释放,它正在自动释放。自动释放就像延迟清理,它意味着“我已经完成了这个,随时可以摆脱它”。有时候代码的另一部分,比如你的一个函数,会在自动释放之前拾取对象(保留)。

自动释放由名为NSAutoreleasePool的类管理。该类维护一堆池,当一个对象被自动释放时,它被添加到堆栈的最顶层池中。排空池会导致它释放已添加到其中的所有对象 - 如果已经释放了足够的对象,它们将被释放。如果您不想,则无需直接管理NSAutoreleasePool个实例;您可以将代码放入@autoreleasepool{}块中,编译器将插入静态NSAutoreleasePool实例。

您可以采取三种方法来删除此邮件。其中一个适用于Mac和iPhone,是KennyTM建议的 - 在您使用自动释放对象的代码周围添加一个自动释放池。对于自动释放Cocoa对象的每个线程,您需要一个,更多是可能的,但通常一个就足够了。第二种选择,虽然只有你的目标是Mac OS,但是要启用垃圾收集。这不会解决您的所有问题,但意味着会自动删除未引用的对象。

在两个平台上,您还可以使用自动引用计数,它指示编译器为您处理内存管理。您仍然需要将自动释放池放在适当的位置,并且有一些“有趣”的交互与免费桥接,但总的来说,如果您正在努力进行引用计数,那么最好自动化它。

如果您不熟悉保留计数和自动释放池,则代码中可能存在其他内存管理问题。我建议您在项目中使用静态分析器(从Xcode的构建菜单中选择“Build& Analyze”)并解决它引发的任何问题。

答案 1 :(得分:1)

  

这是内存泄漏???

  

如果是,我怎么能避免这个?

您需要NSAutoreleasePool。例如,

int main () {
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

  ... your main code ...

  [pool drain];
  return 0;
}

答案 2 :(得分:0)

如果在调用main函数之前看到此消息已记录,那是因为静态初始值设定项正在创建临时变量,而这些变量是在没有池的情况下自动释放的。

这是一个解决方案(我把它放在我的主要功能之上)。在C ++静态初始化器之前调用AppInitFunc,因此在调用静态初始化器之前创建池。

static NSAutoreleasePool* cplusplus_static_pool = nil;
extern void AppInitFunc(void) __attribute__ ((constructor));
void AppInitFunc(void)
{
    cplusplus_static_pool = [[NSAutoreleasePool alloc] init];
}

extern void AppTermFunc(void) __attribute__ ((destructor));
void AppTermFunc(void)
{
//  draining pool here may cause a crash on termination.
//  [cplusplus_static_pool drain];
}

int main(int argc, char *argv[])
{
    /* release the static init pool, create another */ 
    [cplusplus_static_pool release]; 
    cplusplus_static_pool = [[NSAutoreleasePool alloc] init];
    return NSApplicationMain(argc,  (const char **) argv);
}

/* now you can do this and not leak */    
static const NSArray* kArrayOfStrings = [[NSArray arrayWithObjects:@"1", @"2", nil] retain];