• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Leaking Memory
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Leaking Memory


  • Subject: Re: Leaking Memory
  • From: mmalcolm crawford <email@hidden>
  • Date: Fri, 24 Jan 2003 13:58:21 -0800

On Thursday, January 23, 2003, at 06:33 PM, Robert Goldsmith wrote:

Fundamentally, we are all nothing more than probability wave functions,
it looks very likely that the universe has 22 dimensions and time is a
figment of our imagination. This does not stop us pretending we exist,
feeling the universe is something that is happening elsewhere and time
is the most important thing there is.

Until we discover that the universe is composed of NSSuperStrings, this is of little relevance.

It all helps us live our lives without getting stressed. Until a time when "autorelease -- deallocates an object when you don't need it anymore" just doesn't cut it any more,
it will do :)

The problem is that the description simply does not "cut it", and failure to understand the basics of memory management does lead to considerable stress for people.

Both of these statements:

release -- deallocates an object _right away_
autorelease -- deallocates an object when you don't need it anymore (generally at the end of whatever method the autorelease is declared)

are fundamentally wrong:

release
-------
Consider:
NSString *fullName = [NSString alloc] initWithFormat:@"%@ %@",
firstname, lastName];
[myArray addObject:fullName];
[fullName release];

fullName is *not* deallocated _right away_. The array holds on to it.


autorelease
-----------
Simply because an object is autoreleased does *not* mean that it will be deallocated "when you don't need it anymore" -- this broad statement does not take account of any retains that might have been sent in the interim (cf. also release above). Further, it is not "generally [released] at the end of whatever method the autorelease is declared" -- to see why this is (a) wrong and (b) confusing, consider a standard convenience constructor:

+ (Person *) person {
return [[[self alloc] init] autorelease];
}


The misleading / incorrect statements in the original reply will lead to confusion and stress for newcomers -- as indeed your subsequent question suggests:

Of course, the next question (and one not made very clear by any of the
many documents I have read) is exactly -when- autoreleased items are
cleared.

Objects are "cleared" (deallocated) when their retain count drops to 0.

"Generally", that's as much as we need to, or -- in the absence of any other context -- can, say (bearing in mind basic rules of memory management).



In practical terms, however, it may be useful for a developer to be aware of when autoreleased objects will be sent a release message, in order that they may try to determine whether memory usage may become excessive (e.g. if a large number of temporary objects is created and not promptly disposed of).

More information is given in Apple's documentation:

<http://developer.apple.com/techpubs/macosx/Cocoa/TasksAndConcepts/ ProgrammingTopics/MemoryMgmt/index.html#//apple_ref/doc/uid/10000011i>
->
<http://developer.apple.com/techpubs/macosx/Cocoa/TasksAndConcepts/ ProgrammingTopics/MemoryMgmt/Concepts/AutoreleasePools.html>

"NSAutoreleasePools are automatically created and destroyed in applications based on the Application Kit, so your code normally does not have to worry about them. (***The Application Kit creates a pool at the beginning of the event loop and releases it at the end.***)"
(My emphasis.)

So to answer your question; if you have not created any autorelease pools of your own, any autoreleased objects will be sent a release message at the end of the current event loop (one release message per autorelease message they were sent).


There may, as hinted above, be some situations in which you want to create your own autorelease pool:

(1) As per the documentation, "if you spawn a secondary thread, you must create your own autorelease pool as soon as the thread begins executing".
(2) If you create a large number of temporary autoreleased objects.

The important thing to realise about autorelease pools is that they're "nested". An autoreleased object is "added" to the "most recently created" autorelease pool. Consider the following, almost contrived and almost deliberately confusing example:

- (NSDecimalNumber *)total {

NSEnumerator *itemEnumerator = [[self items] objectEnumerator];
Item *item;

NSDecimalNumber *total = [[NSDecimalNumber zero] retain];

while (item = [itemEnumerator nextObject]) {

NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
NSDecimalNumber *amount = [item amount];
if (amount) {
// ****
NSDecimalNumber *newTotal = [[total decimalNumberByAdding:amount] retain];
[total release];
total = newTotal;
}
[myPool release];
}
[total autorelease];
return total;
}

The newTotal NSDecimalNumber created within the loop (at ****) is added to the most-recently-created autorelease pool (myPool). Thus with the somewhat more complex arrangement of retains and releases, we ensure that no sub-totals remain in memory longer than necessary.

Contrast the more straightforward implementation:

- (NSDecimalNumber *)total {

NSEnumerator *itemEnumerator = [[self items] objectEnumerator];
Item *item;

NSDecimalNumber *total = [NSDecimalNumber zero];

while (item = [itemEnumerator nextObject]) {

NSDecimalNumber *amount = [item amount];
if (amount) {
total = [total decimalNumberByAdding:amount];
}
}
return total;
}

Here a potentially large number of temporary subtotals will exist -- by default, assuming no other autorelease pools have been created by the developer -- until the end of the current event loop.

Using lightweight objects like numbers may not be entirely convincing, but it serves to make the example relatively comprehensible (and NSNumber is a convenient example since the only available instance methods return autoreleased objects). Consider the situation when large numbers of other more memory-consuming objects might be created (image manipulation, for instance); use of your own autorelease pools may have a significant advantage in reducing the peak memory footprint of your application. And the only way to ensure that you use these properly, is to ensure that you properly understand memory management.

mmalc
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: Leaking Memory
      • From: Robert Goldsmith <email@hidden>
References: 
 >Re: Leaking Memory (From: Robert Goldsmith <email@hidden>)

  • Prev by Date: Re: Cocoa Code Repository
  • Next by Date: Re: Cocoa Code Repository
  • Previous by thread: Re: Leaking Memory
  • Next by thread: Re: Leaking Memory
  • Index(es):
    • Date
    • Thread