1

If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle ?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
CodenameLambda1
  • 1,299
  • 7
  • 17
  • 2
    Probably for about 1/60th of a second – borrrden Aug 01 '13 at 05:40
  • Its staying a lot. I assigned an object in AppDelegate and then tried to access it in some other ViewController at later instant of time, but the object was still there will all the internal values intact. Hence, I have doubt now. – CodenameLambda1 Aug 01 '13 at 05:43
  • slightly off-topic: ARC is generally preferred these days. Is there a particular reason you prefer not to use it? When you have to debug invalid references, NSZombie objects help alot. – Mitchell Currie Aug 01 '13 at 05:47
  • The object will remain intact, even after it is released to zero, until it is overwritten by something else. – borrrden Aug 01 '13 at 06:17
  • thanks borrrden. I prefer MRC. I am good at MRC and it provides more control over the memory management. However, there was a confusion regarding the static var which struck me up today and I asked. :) – CodenameLambda1 Aug 01 '13 at 07:10

4 Answers4

5

If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle?

Short Answer: You want your global to be a strong reference. In MRC, you must add the retains and releases for globals. In ARC, the global is implicitly strong (and ARC adds them for you).

Long Answer: Under ARC, your static global variable is a strong reference. In MRC, you would retain such a variable when set and then release the previous object. If you did not, then you could still access it after it were deallocated (dangling pointer).

Because it is a strong reference, your object will remain valid until a) the strong reference by the global variable is given up and b) the autorelease pool is drained c) and of course any other strong references are given up.

So if you are using strong references for that global and you never reassign it (logically, giving up the global's strong reference), then your object would never be dealloc'ed.

When you use unsafe nonretained semantics (by decoration in ARC, or the default for a static in MRC), the object would be -dealloced when the current autorelease pool is drained and all strong references are removed. This is easiest to illustrate with a program (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;
 }
}

So if NonRetainedOwnership is true and you use MRC, then your object would typically be -dealloc-ed shortly after -sharedObject returns (assuming whoever called -sharedObject holds no strong reference). In this case, 'shortly' means the pool will often be drained a few frames back in your current callstack, often in AppKit or UIKit when you are on the main thread since I don't see many people explicitly create autorelease pools on the main thread. borrrden said after "1/60th of a second", and the assumption there is that the object is created and autoreleased in the main thread's run loop (correct me if I am wrong). The 'Kits create autorelease pools at each iteration of the main run loop, but your program could be running on a secondary thread or there could be an inner autorelease pool, so the lifetime has the possibility to be shorter or longer. Normally, you don't need to think about these things in much depth -- just use a strong reference here since you really have no other way to ensure the right thing happens with this global variable.

If you simply wrote: @autoreleasepool{[[MONObject new] autorelease];} NSLog("Hi"); then the object would (under normal circumstances) be released by the time NSLog were called.

justin
  • 104,054
  • 14
  • 179
  • 226
  • 1
    Good explanation, although I took "autoreleased object" to mean an object that was sent an autorelease message (and thus impossible under ARC). Although I see how it could also work under ARC (the object is assumed to be autoreleased from other MRC code, etc). – borrrden Aug 01 '13 at 06:53
  • @borrrden thanks. i just assumed the OP meant an object returned by a method which (behaves as one which) returns an autoreleased object -- or that she/he was using MRC. curious; you write as though there is a guarantee that autorelease pools are not used/required in ARC programs (apart from interaction with MRC programs). – justin Aug 01 '13 at 07:01
  • @justin It was not my intention to write in that way. The autorelease pool still has an effect under ARC, of course, it is just a lot more subtle. With MRC, however, it will be deallocated in the very next drain cycle unless otherwise retained. I just thought it would benefit from a (more or less) precise answer about when it would be deallocated under MRC since most of your answer focuses on the ARC side. – borrrden Aug 01 '13 at 07:33
  • @borrrden ah. ok. i misinterpreted that. – justin Aug 01 '13 at 08:43
  • 1
    @Justin : nice detail. This detail is kind of singleton declaration. :) – CodenameLambda1 Aug 01 '13 at 09:50
  • @CodenameLambda1 yup - i wouldn't use that code in real life. i have had too many pains with globals and singletons, but it's there to demonstrate memory semantics for globals. cheers – justin Aug 01 '13 at 10:03
1

The declaration of variable doesn't matter as such, The thing what matters is when did you assigned an autoreleased object to it, If it is assigned under any autorelease pool than it would drain it else it would be released on program termination by autorelease pool in main method!

The Variable is just a pointer and does not retain the object unless done explicitly, thats why retaining static objects is preferred: Why retain a static variable?

Community
  • 1
  • 1
Asif Mujteba
  • 4,596
  • 2
  • 22
  • 38
0

When the pool is 'drained'. This may not happen right away. Please see a similar question

Community
  • 1
  • 1
Mitchell Currie
  • 2,769
  • 3
  • 20
  • 26
-2

It depends. If the variable is initialized only once, and should stay around for the lifetime of the application, then no, it shouldn't be released (its memory will essentially be freed when the application exits, anyway). If, however, the value of the static variable changes, then yes, the previous object should be released when the static variable is set to a new object.

Aslam
  • 1