• 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: A few questions about Memory Management
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A few questions about Memory Management


  • Subject: Re: A few questions about Memory Management
  • From: James Spencer <email@hidden>
  • Date: Sat, 12 Feb 2005 10:06:03 -0600


On Feb 11, 2005, at 7:56 PM, Adrian R. Foltyn wrote:

Hi there,

I have a couple of questions about Memory Management and hope that somebody finds time to help me out here.

Other people have answered your questions but there are a couple of things that were omitted that might help:

----------------------------------------------------------------
If I dealloc a NSArray holding other objects that were previously alloced and inited the objects that were contained in the array are neither released nor dealloced?


----------------------------------------------------------------

As has been pointed out, you should not delloc anything; you call release and if the retain count drops to zero, the system will dealloc the object. And has also been pointed out, when you add objects to an array, they get are retained by the array. They are then released when the array is dealloced. The additional point here is that if you created the objects through alloc and init the release message sent when the array is dealloced will NOT cause the individual objects to be dealloced unless you have another release somewhere. Thus, if you do something like the following:


NSMyObject	 *myObject = [[NSMyObject alloc] init];
NSArray *theArray = [NSArray arrayWithObject:myObject];

then you also need to follow this up with something like:

[myObject release};

or you will leak. In the above code, myObject essentially gets two retains, one when it is alloced and one when it is added to the array. If you don't do an explicit release, then the only release it will ever get is when the array is deallocated and because the retain count would still be one, the object would not get released.

Note also that, as discussed below, theArray, having been created with a convenience method and not will alloc, is an autoreleased object and will go away when the autorelease pool is destroyed, i.e. the next time through the event loop assuming you haven't created your own autorelease pool.


If I understood correctly onelinecoding in Cocoa is bad if you care about how much memory your program uses. As an example:


NSString *dreamWorld = [[[NSString initWithContentsOfFile:@"/path/to/realWorld.txt"] componentsSeparatedByString:@"hate"] componentsJoinedByString:@"love"];

With the above line I will never have the chance to send a release message to the NSString instance that stores the contents of the file and the NSArray instance that stores the delimited text as I don't have any pointers in place that reference to them. Neither the end of the method this code is executed in nor the deallocation of the object this method is used in will result in removing the NSString and NSArray instance from memory.
...

This won't compile as the NSString class does not have an initWithContentsOfFile class method. As has been pointed out, you would have to either alloc a string or call a class convenience method.


Having said that, the only string that you would have to worry about explictly releasing in the above code would be the string you create with alloc. Unfortunately, this wold leak Thus, if you modified the above to be:

NSString *dreamWorld = [[[[NSString alloc] initWithContentsOfFile:@"/path/to/realWorld.txt"]
componentsSeparatedByString:@"hate"] componentsJoinedByString:@"love"];


would leak the string for which you have no reference but which was created by alloc. Your choices are to either do what you noticed and keep a reference to that string so you can release it:

NSString *realWorld = [NSString initWithContentsOfFile:@"/path/to/realWorld.txt"];
NSString *dreamWorld = [[realWorld componentsSeparatedByString:@"hate"] componentsJoinedByString:@"love"];
[realWorld release];


As with the array example, dreamWorld here is an autoreleased object so you don't have to release it; it will be released the next time the autorelease pool is destroyed. Actually you may have to retain it if you want to keep it around outside the local scope.

----------------------------------------------------------------
In the documentation for NSArray there is this example code:
NSArray *pathArray = [NSArray arrayWithObjects:@"System", @"Library", nil];
NSLog("The path is /%@.\n", [pathArray componentsJoinedByString:@"/"]);


Is it impossible to dealloc the resulting NSString instance of the componentsJoinedByString: call?

First of all, there is what I assume is a typo in the above: NSLog expects an NSString so the second line needs to be:


NSLog(@"The path is /%@.\n", [pathArray componentsJoinedByString:@"/"]);

More to the point, and this deserves stressing so it'll get repeated here, you don't dealloc anything. You release the objects, reducing the retain count by one. When the retain count gets to zero, the system will dealloc the object.

Having said that, you are correct that you can't send ANY messages to what is essentially a temporary created by componentsJoinedByString. However, you don't need to: ANY object that is created by ANY means other than alloc or copy (or their obvious variations) are provided to you autoreleased. Essentially this means that the object already has been released but the actual release message has been deferred so you can actually do something with the object before it is destroyed (in this case pass it to NSLog()). Later, when the autorelease pool is destroyed, an actual release message will be sent to the string object and, assuming that it's retain count drops to zero at that point (which in this case it necessarily will as in this context the only opportunity to effect the retain count was when the temporary string was created in the first place.)

Would it be safe to say that example code in the documentation is not a good place to study memory management as it tries to demonstrate a concept in brief?

My experience is that most of the example code in the documentation does NOT explictly leak; it may not contain all the explicit release or autorelease calls but the code presented won't typically leave zombie objects that can't be accessed but nevertheless need releasing. The example code above does NOT leak: pathArray is autoreleased as are all temporary objects. (Note that there are a lot more such objects in the above than simply the string created by componentsJoinedByString: each of the explicit string objects are autoreleased too: @"System", @"Library" and "The path is /%@.\n" too. ) That said, it is probably wise to use code snippets (as versus full blown sample applications) for their announced purpose and be wary of using them for unannounced purposes such as in this example memory management.


If I would completely ignore memory management while writing a simple command line tool does the system free the objects in memory after the tool exits?

What happens to the memory if it crashes?

When a process, whether a simple command line tool or a full blown AppKit application, terminates whether regularly or by crashing, the memory that was allocated is all recovered. In the meantime though if you haven't done anything regarding memory managment, even a simple command line tool will be throwing error messages even if they don't actually crash the program. For example, if you put the above sample code (the pathArray and NSLog() code) in a simple Cocoa foundation tool that doesn't create an NSApplication and which doesn't explictly create it's own autorelease pool, it will run and the run log will display the string as expected but you will also receive error messages such as the following:


2005-02-12 09:52:46.125 TestFoundationTool[3991] *** _NSAutoreleaseNoPool(): Object 0x308810 of class NSCFString autoreleased with no pool in place - just leaking

James P. Spencer
Rochester, MN

email@hidden

"Badges??  We don't need no stinkin badges!"

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >A few questions about Memory Management (From: "Adrian R. Foltyn" <email@hidden>)

  • Prev by Date: Re: NSImageView only for images?
  • Next by Date: Re: NSImageView only for images?
  • Previous by thread: Re: A few questions about Memory Management
  • Next by thread: Re: A few questions about Memory Management
  • Index(es):
    • Date
    • Thread