一个全局声明的自动释放静态对象在内存中存活多久



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

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

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

长答案:在ARC下,您的静态全局变量是一个强有力的参考。在MRC中,您将在设置时保留这样一个变量,然后释放前一个对象。如果没有,那么在解除分配后仍然可以访问它(悬挂指针)。

因为它是一个强引用,所以您的对象将保持有效,直到a)全局变量的强引用被放弃,b)自动释放池被耗尽,c)当然还有任何其他的强引用都被放弃。

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

当您使用不安全的非保留语义(通过ARC中的修饰,或MRC中static的默认值)时,当当前自动释放池耗尽并删除所有强引用时,对象将为-dealloced。这是最容易用程序(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,那么您的对象通常会在-sharedObject返回后不久被-dealloc-ed(假设调用-sharedObject的人没有强引用)。在这种情况下,"很快"意味着池通常会在当前调用堆栈中的几帧后耗尽,通常是在主线程上的AppKit或UIKit中,因为我没有看到很多人在主线程中明确创建自动释放池。borrrden在"1/60秒"之后说,假设对象是在主线程的运行循环中创建并自动释放的(如果我错了,请纠正我)。Kit在主运行循环的每次迭代中都会创建自动释放池,但您的程序可能在辅助线程上运行,也可能有内部自动释放池。因此,生存期可能更短或更长。通常,你不需要深入思考这些事情——只需在这里使用一个强有力的参考,因为你真的没有其他方法来确保这个全局变量发生正确的事情。

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

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

变量只是一个指针,除非明确执行,否则不会保留对象,这就是为什么首选保留静态对象:为什么要保留静态变量?

当池被"排空"时。这可能不会马上发生。请参阅类似的问题

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

最新更新