全局声明的自动释放静态对象在内存中存活多长时间?

时间:2013-08-01 05:38:53

标签: ios objective-c memory-management

如果我在全局范围的类文件中声明一个静态对象句柄。分配给此句柄的对象是自动释放的对象。然后,在我的应用程序生命周期中,此对象将在内存中保留多长时间?

4 个答案:

答案 0 :(得分:5)

  

如果我在全局范围的类文件中声明一个静态对象句柄。分配给此句柄的对象是自动释放的对象。然后,在我的应用程序生命周期中,此对象将在内存中保留多长时间?

简答:您希望您的全局成为强大的参考。在MRC中,您必须为全局变量添加保留和释放。在ARC中,全局隐含强大(ARC为您添加它们)。

长答案: 在ARC下,您的静态全局变量是一个强引用。在MRC中,您将在设置时保留此变量,然后释放上一个对象。如果你没有,那么你可以在它被取消分配后(悬挂指针)访问它。

因为它是一个强引用,所以你的对象将保持有效,直到a)全局变量的强引用被放弃,b)自动释放池被排出c),当然任何其他强引用都被放弃了。< / p>

因此,如果您对该全局使用强引用并且永远不会重新分配它(逻辑上,放弃全局的强引用),那么您的对象永远不会被dealloc'编辑。

当您使用不安全的非重定义语义(通过ARC中的装饰,或MRC中的static的默认值)时,在当前自动释放池耗尽并且所有强引用时,对象将为-dealloc被删除。这是用程序(MRC)最简单的说明;

static MONObject * GlobalObject;
//
// In MRC, you must add the reference counting to ensure you do not end up with a dangling
// pointer, so false is what how your program should be written in MRC.
//
// In ARC, your program will look like NonRetainedOwnership because it treats the global
// as a strong reference.
static const bool NonRetainedOwnership = ...T/F...;

...

// assume GlobalObject is accessed from one thread only -- i won't bother with
// the supporting code to illustrate how this should be made thread safe.
- (MONObject *)sharedObject
{
 if (nil == GlobalObject) {
  if (NonRetainedOwnership) {
      // don't do this! lifetime will be determined by strong client references
      // and the reference you rely on now will be lost when the thread's current
      // autorelease pool is drained -- leaving you with a dangling pointer which
      // will cause issues when -sharedObject is called again.
    GlobalObject = [[MONObject new] autorelease];
  }
  else {
     // Good - keep a strong reference:
   GlobalObject = [MONObject new];
  }
 }
 return GlobalObject;
}

- (void)disposeSharedObject
{
 if (NonRetainedOwnership) {
  GlobalObject = nil;
 }
 else {
  // remove our reference, which was established at [MONObject new]
  // assuming there are no strong external references, the object
  // will be dealloc'ed -- but you should not make that assumption
  // if you return it.
  [GlobalObject release], GlobalObject = nil;
 }
}

因此,如果NonRetainedOwnership为true并且您使用的是MRC,那么您的对象通常会在-dealloc返回后不久-sharedObject - 假设无论谁调用-sharedObject都没有强引用。在这种情况下,“很快”意味着池通常会在当前的callstack中耗尽几帧,当你在主线程上时通常在AppKit或UIKit中,因为我没有看到很多人在主要线程上显式创建自动释放池线。 borrrden在“1/60秒”之后说,假设在主线程的运行循环中创建并自动释放对象(如果我错了,请纠正我)。 'Kits在主运行循环的每次迭代中创建自动释放池,但是您的程序可能在辅助线程上运行,或者可能存在内部自动释放池,因此生命周期可能更短或更长。通常情况下,你不需要深入思考这些事情 - 只需在这里使用强引用,因为你真的没有办法确保这个全局变量正确发生。

如果您只是简单地写了:@autoreleasepool{[[MONObject new] autorelease];} NSLog("Hi");那么该对象将(在正常情况下)在NSLog被调用时被释放。

答案 1 :(得分:1)

变量的声明并不重要,重要的是你什么时候为它分配了一个自动释放的对象,如果它在任何自动释放池下被分配,那么它将耗尽它,否则它将在程序终止时被释放通过main方法中的自动释放池!

变量只是一个指针,除非明确地完成,否则不会保留对象,这就是首选保留静态对象的原因:Why retain a static variable?

答案 2 :(得分:0)

当游泳池“耗尽”时。这可能不会马上发生。 请参阅a similar question

答案 3 :(得分:-2)

这取决于。如果变量只初始化一次,并且应该在应用程序的生命周期内保持不变,那么不应该,它不应该被释放(无论如何,当应用程序退出时,它的内存基本上会被释放)。但是,如果静态变量的值发生变化,则是,当静态变量设置为新对象时,应释放上一个对象。