1

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

4

4 回答 4

5

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

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

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

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

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

当您使用不安全的非保留语义时(通过 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后不久被 -ed -sharedObject(假设谁调用-sharedObject没有强有力的参考)。在这种情况下,“很快”意味着池通常会在您当前的调用堆栈中耗尽几帧,通常在 AppKit 或 UIKit 中,当您在主线程上时,因为我没有看到很多人明确地在主线程上创建自动释放池线。borrrden 在“1/60 秒”之后说,并且假设对象是在主线程的运行循环中创建并自动释放的(如果我错了,请纠正我)。'Kits 在主运行循环的每次迭代中创建自动释放池,但您的程序可能在辅助线程上运行,或者可能存在内部自动释放池,因此生命周期可能会更短或更长。通常情况下,你不会

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

于 2013-08-01T06:30:29.943 回答
1

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

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

于 2013-08-01T05:44:13.297 回答
0

当游泳池“排干”时。这可能不会立即发生。请看一个类似的问题

于 2013-08-01T05:43:24.747 回答
-2

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

于 2013-08-01T05:50:19.897 回答