I am calling a function repeatedly with a loop, and the loop runs inside of a thread. The thread has an autorelease pool.
I have the following code inside that function:
NSXMLDocument* undoXML;
NSData* undoData = [NSData dataWithContentsOfFile:undoFilePath];
undoXML = [[NSXMLDocument alloc] initWithData:undoData options:NSXMLDocumentTidyXML error:&err];
NSData* undoData2;
undoData2 = [undoXML XMLData];
[undoData2 release];
[undoXML release];
I'm getting the following strange results:
My program is leaking memory every time this function is called by the loop.
When I add the following code to the function:
NSData* undoData3;
undoData3 = [undoXML XMLData];
[undoData3 release];
My program leaks even more memory than before.
I'm really confused and I badly need help figuring out what's going on. Maybe my autorelease pool isn't working correctly? Why is this happening?
Are you sure it is leaking? Or is it simply growing in size?
What does your loop look like and how is the autorelease pool integrated into it?
The autorelease pool must be inside the loop or your loop will just build up tons of memory over time. That the leaks instrument doesn't show leaks indicates that you have violated the memory management rules or your loop is incorrect.
Try running Instruments on your project w/ the leak detection settings. This should identify exactly where your leak is occurring (even in the system libraries).
Run -> Run With Performance Tool -> Leaks
undoData should be preset to be autoreleased (according to naming convention dataWithContentsOfFile: returns an autoreleased object). But unless you have your own autorelease pool, nothing that is set to autorelease will actually be deallocated until the active pool is drained (i.e. sometime after your function returns).
Your thread may have its own autorelease pool, but unless you are creating one inside your own function, nothing will be deallocated until after your function exits.
If you want to trigger the draining of autoreleased objects in the middle of a function (say once per loop), you need to manage your own autorelease pool.
while(looping) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do stuff that produces autoreleased objects
[pool drain];
}
Also, per cobbal's comment on your question, it looks like you should not be releasing undoData2 (or undoData3). Based on the naming convention -[NSXMLDocument XMLData] should be returning an autoreleased object.
If you have access to the source code of the NSData class you should look at what objects are being instantiated when undoData3 is created. I say this because you create the object and immediately destroy it. The issue must be that memory is being allocated inside the class but not being deallocated in it's destructor.
Related
I am calling a selector which I want to use to fire off a background process with the following
[self performSelectorInBackground:#selector(startSync) withObject:nil];
For an example, lets say startSync looks something like this
-(void)startSync {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// expensive background process
Sync *sync = [Sync new];
[sync performSync];
[sync release];
[pool release];
}
The really intensive processing is happening in "performSync" of the sync object. It's retrieving some XML, parsing it into an array, and inserting it into a MySQL database. The process itself seems to be working fine and the Analyzer isn't showing any leaks, but using the profiler and doing a baseline Heap Mark at the beginning before it runs and then again after it runs is showing about a 5mb gain. To the best of our knowledge (no pun intended) we are properly allocating and releasing objects in the performSync process.
The question is I am running this process in the background, if I am creating an AutoreleasePool for it, and releasing it at the end of the background process, shouldn't it dealloc everything related to the background process when it is over? I don't have a good understanding of why all of the allocated objects aren't getting destroyed.
The release will only happen at the end of the event loop
We were missing a close database statement each time we were doing a record insert, which was creating more connections and causing our problem. After doing so, our baseline heap mark was at 1.22mb and our ending heap mark was 1.22mb, exactly as I was expecting.
I've read apple documentation to assert that I was doing the memory management correctly but some questions raised.
Question 1:
They exhibit this code snippet as wrong :
in obj implementation:
- (NSString *)method1 {
NSString *string = [[NSString alloc] initWithFormat:#"%# %#", firstName, lastName];
return string;
}
... later ...
NString* myString = [obj method1];
NSLog("%#", myString);
[myString release];
Apple Doc :
You own the string returned by alloc, but lose the reference to it before you get a chance to relinquish ownership. Following the memory management rules, this would result in a memory leak, since the caller has no indication that they own the returned object.
Since I'm taking care of releasing the object that has been allocated previously, there is no memory leak, right ? What do they mean by "lose the reference to it" ?
It is wrong only regarding apple's memory management recommendations (the caller has no indication that they own the returned object) or this is also technically wrong ?
Question 2 :
This is about autoreleased objects availability :
Example code:
in obj1 implementation:
- (NSString *)methodA {
NSString *string = [[NSString alloc] initWithFormat:#"%# %#", firstName, lastName];
return [string autorelease];
}
in obj2 implementation:
- (NSString *)methodB:(NSString *)inputString {
NSLog("%#",inputString)
//*other call of methods with arg inputString*//
}
... later ...
NString* myString = [obj1 methodA];
[obj2 method2:myString];
How far (or deep) following my functions calls will the autorelease object returned by obj1 will be available. Regarding apple's documentations "Autorelease objects will be available within their variable scope". Should I retain it at some point ?
Q1: It is wrong only regarding apple's memory management recommendations (the caller has no indication that they own the returned object) or this is also technically wrong ?
Technically this is correct as you release myString after using it. However if you follow Apples guidelines for method naming (strongly recommended), this is clearly wrong:
You own any object you create.
You “create” an object using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy).
method1 doesn't contain create, alloc, new or copy - thus per the guideline the caller doesn't own the object and doesn't have to release it.
Q2: How far (or deep) following my functions calls will the autorelease object returned by obj1 will be available. Regarding apple's documentations "Autorelease objects will be available within their variable scope". Should I retain it at some point ?
Auto-released objects will be alive until the closest Autorelease Pool is drained, see Autorelease Pools:
An autorelease pool is an instance of NSAutoreleasePool that “contains” other objects that have received an autorelease message; when the autorelease pool is deallocated it sends a release message to each of those objects. An object can be put into an autorelease pool several times, and receives a release message for each time it was put into the pool. Thus, sending autorelease instead of release to an object extends the lifetime of that object at least until the pool itself is released (the object may survive longer if it is retained in the interim).
...
The Application Kit automatically creates a pool at the beginning of an event cycle (or event-loop iteration), such as a mouse down event, and releases it at the end, so your code normally does not have to worry about them. There are three cases, though, where you might use your own autorelease pools:
...
So, if you need your instances to stay alive after the corresponding autorelease pool was drained, take ownership by retaining them. Otherwise you usually just let them be handled by the pool.
Since I'm taking care of releasing the object that has been allocated previously, there is no memory leak, right ?
right
What do they mean by "lose the reference to it" ?
you hold no pointers for the object, such that the object may not be accessed in your program.
It is wrong only regarding apple's memory management recommendations (the caller has no indication that they own the returned object) or this is also technically wrong ?
also correct. the static analyzer will prolly cry too
How far (or deep) following my functions calls will the autorelease object returned by obj1 will be available. Regarding apple's documentations "Autorelease objects will be available within their variable scope". Should I retain it at some point ?
this is a little more complex. autorelease pools are stacked upon each other by thread. that's why you must create one when entering a thread or new event loop iteration, and also why it is a good idea to create them explicitly when performing large operations which create many (autoreleased) allocations.
finally the last pool in the stack (for the thread) is destroyed at the end of the run loop's iteration.
if the object is created under an autorelease pool you create explicitly, then you must retain it to use it beyond the lifetime of the pool which it was created in.
similarly, you must formally retain/copy when passing to other threads. typically, this happens immediately - you just create a copy or retain the formal arguments when entering the implementation of the secondary thread.
Consider the following program:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Insert code here...
NSLog(#"Programming is Fun !");
[pool drain];
return 0;
}
I don't understand why pool is needed there as the same program can be also written as this:
int main (int argc, const char * argv[]) {
NSLog(#"Programming is Fun !");
return 0;
}
What is a purpose of using an auto release pool? Why and when do we need them? Are they mandatory in every objective C program?
If i don't want to auto release any object, do I also need to use an Auto Release pool ?
NSObject contains a neat function called autorelease. This means all objects in Objective-C contain this function.
This function inserts self into the autorelease pool, delaying the call to object's release function until the autorelease pool is deallocated. Most internal APIs use an autorelease pool, and beside the one located in main(), there is one allocated and deallocated in UIKit's main loop in every pass.
In short: it's the queue for delayed decrement of reference counter.
Example on where autorelease is hidden:
[NSString stringWithUTF8String:"some string"];
This object is allocated, and autorelease is called on it. How would you use it yourself?
MyObject *obj = [[[MyClass alloc] init] autorelease];
Why is this good? When you return this object, the calling function does not need to take care to release this object, and optionally it can retain it (but doesn't have to).
To expand and clarify four years later:
While UIKit and AppKit create and drain an NSAutoreleasePool during the course of their main runloop, in your non-GUI program you need to create it yourself. Various code expects having an NSAutoreleasePool present, and since you didn't initialize a GUI framework nor you use one, there is no code that will magically create it for you.
While NSLog() and a constant NSString in your example don't require a pool, even the trivial [NSMutableArray array] does, given that it can actually be interpreted as [[[NSMutableArray alloc] init] autorelease].
But if i don't want to auto release any object, then also do i need to use Auto Release pool ??
Also note that the Cocoa library uses autorelease extensively. So, even if you think you don't use the pool in your code, you need to prepare the pool.
I have found reason...
"If a pool is not available, autoreleased objects do not get released and you leak memory. In this situation, your program will typically log suitable warning messages."
You typically do not have to create an autorelease pool block yourself, or even see the code that is used to create one. three occasions when you might use your own autorelease pool blocks,
If you are writing a program that is not based on a UI framework,
such as a command-line tool.
If you write a loop that creates many temporary objects - You may use
an autorelease pool block inside the loop to dispose of those objects
before the next iteration. Using an autorelease pool block in the
loop helps to reduce the maximum memory footprint of the application.
If you spawn a secondary thread - You must create your own
autorelease pool block as soon as the thread begins executing;
otherwise, your application will leak objects.
A general introduction can be found on Apple's website:
Autorelease Pools and Ownership and Disposal
Check out the NSAutoreleasePool documentation
I have a problem with the memory management in Objective-C. Say I have a method that allocates an object and stores the reference to this object as a member of the class. If I run through the same function a second time, I need to release this first object before creating a new one to replace it. Supposing that the first line of the function is:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
This means that a different auto-release pool will be in place. The code to allocate the object is as follows:
if (m_object != nil)
[m_object release];
m_object = [[MyClass alloc] init];
[m_object retain];
The problem is that the program crashes when running the last line of the method:
[pool release];
What am I doing wrong ? How can I fix this ?
Regards
Alan
First get a general understanding of the objective c memory management. You are confusing a lot of different things here. For example you don't have to retain the m_object since alloc already sets up the retain count with 1. Also normally you dont release you AutoReleasePool when you release a object. Like I said look up the documentation for memory management (pretty good actually).
Autorelease pools handle objects that have been specifically autoreleased
Example:
[object autorelease];
You have to have at least one NSAutoreleasePool in your program in case some code attempts to autorelease an object. If this is your only NSAutoreleasePool then releasing the pool maybe causing your problems.
I still have some unclear understand about release and autorelease. What are the difference between both of them? I have this code. For facebook connection. I crash it sometimes when I go to Facebook login, I doubting maybe it is because I don't release the object nicely.? Thanks for any helps
if (_session.isConnected) {
[_session logout];
} else {
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease];
[dialog show];
}
The Memory Management Programming Guide for Cocoa will soon be your best friend. In brief, object instances in Cocoa are memory managed using reference counting (unless, of course you're using garbage collection on OS X). An object indicates that it wants to 'retain' an ownership interest in an other instance--keep it from being deallocated--by sending it a -retain message. An object indicates that it wants to release that interest by sending the other instance a -release message. If the number of objects that have 'retained' and ownership interest in an object drops to 0 (i.e. when the last of the owning instances sends a -release message), the instance with a 0 retain count is deallocated.
It's sometimes convenient to say "I want this instance to be released some time in the future". That's the purpose of -autorelease. Sending an -autorelease message adds the receiver to the current NSAutoreleasePool. When that pool is drained, it sends a -release message to all the instances in the pool. An NSAutoreleasePool is automatically created at the start of each iteration of each thread's run loop and drained at the end of that iteration. Thus, you can do something like this in a method:
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
The caller of this method will get back an instance that they can -retain if they wish to keep it. If they don't retain it, it will stick around at least until the enclosing autorelease pool is drained:
- (void)someOtherMethod {
...
id instance = [obj myMethod];
... // do more with instance, knowing that it won't be dealloc'd until after someOtherMethod returns
}
Releasing means you release that right away.
Autoreleasing means you want the variable to be released on the next autorelease pool.
You use autorelease when you want to keep retaining the variable but don't want to create a memory leak. You use release when you don't need the variable anymore.
Sample:
- (NSNumber *)return5 {
NSNumber * result = [[NSNumber alloc]initWitnInt: 5];
[result autorelease];
return result;
}
Why do we use autorelease there?
If we use [result release] instead, variable result will be destroyed AT that time. Which means that the returned value will be garbage.
If we do not release at all, variable result will be hold FOREVER incurring memory leak.
We can tell every caller to the function to release result but that would be a headache and prone to error.
So we use autorelease. We mark the variable to be released on the next autorelease pool. Basically we mark the variable to be released near the alloc. Hence the mantra alloc is paired with release in the same function holds all the time.
Actually, you'll do fine changing all release into autorelease. Your memory use won't be efficient, however, the effect is minimal. All variables, in all programming language is effectively autoreleased.
Anyway, use ARC.
background discussion:
objective-c is reference counted, so objects are deleted when the reference count reaches 0. release reduces the reference-count immediately, autorelease reduces it when the autorelease-pool is popped
when to use:
use autorelease when allocating the object if
you do not need it after the current function
it will be retiained by some other objet/function and will be released by a later by the retaining code
when the logic of the current function is tricky, so you would have to send release in a dozen different places before doing a return
use "manual" release
to revert a previous retain (in case you are implementing a library)
if you need precise control of freeing objects (e.g. they use lots of memory or the autorelease pool will not be popped for some time)
but really my freand:
read the Memory Management Programming Guide for Cocoa as suggested by Barry and run your code with instruments (zombies and leaks) often to catch any and almost all memory management errors.
Erik
According to the Memory Management Programming Guide for Cocoa:
The autorelease method, defined by
NSObject, marks the receiver for later
release. By autoreleasing an
object—that is, by sending it an
autorelease message—you declare that
you don't want to own the object
beyond the scope in which you sent
autorelease.
Also:
The autorelease method thus allows
every object to use other objects
without worrying about disposing of
them.