Does this Objective-C code leak memory? - objective-c

One thing I'm concerned about is I create two ints, but don't release them. Would it be better to make them NSIntegers?
-(void) flipCoin {
int heads = [headsLabel.text intValue];
int tails = [tailsLabel.text intValue];
if (random() %2 ==1 )
{
heads++;
}
else {
tails++;
}
headsLabel.text = [NSString stringWithFormat:#"%d", heads] ;
tailsLabel.text = [NSString stringWithFormat:#"%d", tails];
}

As sha notes, local variables get allocated in the current stack frame. As soon as the current function call returns, the stack gets "popped", and the memory occupied for the current call is not released so much as abandoned, until it is overwritten by the next call that gets pushed into that part of the stack.
So why do we have to release variables like this:
MyClass *myObject = [[MyClass alloc] init];
Well, you actually don't have to worry about "myObject". It's on the stack, just like your ints, and it will get cleaned up when the current call finishes.
What you have to worry about is the memory that myObject—which is a pointer—points to. It's off somewhere on the heap. Constructing an object involves asking the runtime for some semi-permanent place to put it; that process returns a memory address, which your pointer stores.
alloc and release are Objective-C idioms that largely replace C's malloc() and free() functions, but all of them ultimately are asking the computer to set aside memory on the heap, and all of that memory must ultimately be returned, either through an autorelease pool, a release message, or a free() call.

int is what is known as a primitive type. It is not a pointer to an Objective-C object so you cannot release it. You can't even send a message to it.
NSInteger is also a primitive type in the sense that it is a typedef to a primitive type (long usually). So you can't release that either.
What do you need to release? You need to release any object you obtained by sending new, alloc or a method containing copy. You also need to release objects to which you have sent retain. So all of the local variables in the following must be released:
-(void) foo
{
NSString* aString = [[NSString alloc] init];
NSString* aString2 = [aString copy];
NSString* aString3 = [someOtherString retain];
NSString* aString4 = [#"some string" copy];
}
NB due to implementation details, you would actually get away with not releasing the aString4 but you don't need to worry about it.

No. Your heads and tails variables are local and stored on the stack. This won't cause a leak. Your two NSString assignments near the bottom are created using convenience constructors and will be autoreleased for you.

All default datatypes (int, char, BOOL, etc) are automatically managed for you, and do not (and cannot) be released (for all intents and purposes).
NSIntegers behave likewise, as they are just signed ints (or signed longs on 64-bit machines).
Objects you initialize, however, like NSString or NSArray will usually have to be released (unless they are autoreleased, like the NSStrings at the bottom of your code). If you ever call -alloc and -init on something, you will have to later release it. If you ever doubt whether a method returns an autoreleased object, just read the documentation (it will tell you).
Also, if you want to read up on memory management, there are plenty of wonderful sources that will teach you (Google is a great place to start!), and if you ever think that your code leaks memory, run it through Instruments, and you'll be able to tell...

Related

ARC and __unsafe_unretained

I think I have a pretty good understanding of ARC and the proper use cases for selecting an appropriate lifetime qualifiers (__strong, __weak, __unsafe_unretained, and __autoreleasing). However, in my testing, I've found one example that doesn't make sense to me.
As I understand it, both __weak and __unsafe_unretained do not add a retain count. Therefore, if there are no other __strong pointers to the object, it is instantly deallocated (with immutable strings being an exception to this rule). The only difference in this process is that __weak pointers are set to nil, and __unsafe_unretained pointers are left alone.
If I create a __weak pointer to a simple, custom object (composed of one NSString property), I see the expected (null) value when trying to access a property:
Test * __weak myTest = [[Test alloc] init];
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: (null)
Similarly, I would expect the __unsafe_unretained lifetime qualifier to cause a crash, due to the resulting dangling pointer. However, it doesn't. In this next test, I see the actual value:
Test * __unsafe_unretained myTest = [[Test alloc] init];
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: Hi!
Why doesn't the __unsafe_unretained object become deallocated?
[EDIT]: The object is being deallocated... if I try to substitute lines 2 - 3 with NSLog(#"%#", myTest); the app crashes (and an overridden dealloc in Test is being called immediately after the first line). I know that immutable strings will continue to be available even with __unsafe_unretained, and that a direct pointer to the NSString would work. I am just surprised that I could set a property on a deallocated object (line 2), and that it could later be dereferenced from a pointer to the deallocated object it belonged to (line 3)! If anyone could explain that, it would definitely answer my question.
I am just surprised that I could set a property on a deallocated object (line 2), and that it could later be dereferenced from a pointer to the deallocated object it belonged to (line 3)! If anyone could explain that, it would definitely answer my question.
When the object is deallocated it is not zeroed. As you have a pointer to the deallocated object and the property value is stored at some offset to that pointer it is possible that storing and retrieving that property value will succeed after deallocation, it is also quite possible that everything will blow up for some reason or other.
That your code works is quite fragile, try debugging it with "Show Disassembly While Debugging" and stepping through, you'll probably hit an access violation, or take down Xcode itself...
You should never be surprised that strange things happen in C, Objective-C, C++ or any of the family; instead reserve your surprise for so few strange things happening!
Because the constant string in objc is a constant pointer to a heap address and the address is still valid.
edited after comment:
Maybe because the memory at the test objects address hasn't been overwritten and still contains that object? Speculating....
You can see when Test is deallocated by implementing its -dealloc method and adding some simple logging.
However, even if Test is deallocated immediately, the memory it occupied in RAM may remain unchanged at the time you call myVal.
#"hi!" produces a static global constant string instance that is, effectively, a singleton. Thus, it'll never be deallocated because it wasn't really allocated in the first place (at least, it really isn't a normal heap allocation).
Anytime you want to explore object lifespan issues, always use a subclass of NSObject both to guarantee behavior and to make it easy to drop in logging hooks by overriding behavior.
Nothing strange there…
You need to have at least 1 strong reference to object to keep it alive.
Test * anTest = [[Test alloc] init];
Test * __weak myTest = anTest;
myTest.myVal = #"Hi!";
NSLog(#"Value: %#", myTest.myVal); // Prints Value: (Hi)

When and when to not allocate memory to objects

NSArray *array = [dictionary objectForKey:#"field"];
and
NSArray *array = [[NSArray alloc] initWithArray:[dictionary objectForKey:#"field"]];
I see both kind of approaches very frequently in objective C code.
When tried to understand, I found both of them used in similar situation too, which makes contradiction. I am not clear on when I should use 1st approach and when 2nd one?
Any idea?
Detailed explanation and useful references are moms welcome.
First off, those two examples are doing slightly different things. One is retrieving something from an existing dictionary and one is creating a new array by retrieving something from an existing dictionary (the value of that key is an array).
But, if you're asking the difference between getting objects by alloc vs. convenience methods. ([NSString alloc] init vs [NSString stringWith ...), by convention, you own anything that you call alloc, new copy or mutableCopy on. Anything that you call that is not those, is autoreleased.
See the memory guide here. Specifically, look at the rules.
Getting an autoreleased object means it will go away at some point in the near future. If you don't need to hold onto outside the scope of that function, then you can call autorelease on it or use one of the convenience methods that's not alloc, etc...
For example:
// my object doesn't need that formatted string - create the autoreleased version of it.
- (NSString) description {
return [NSString stringWithFormat:#"%# : %d", _title, _id];
}
// my object stuffed it away in an iVar - I need the retained version of it. release in dealloc
- (void) prepare {
_myVal = [[NSString alloc] initWithFormat:"string I need for %d", _id];
}
In the first example, I created a convenience methods for others to call, my class doesn't need that object beyond the scope of that method so I create the autoreleased version of it and return it. If the caller needs it beyond the scope of his calling method, he can retain it. If not he can use it and let it go away. Very little code.
In the second example, I'm formatting a string and assigning it to an iVar variable that I need to hold onto for the lifetime of my class so I call alloc which will retain it. I own it and releasing it eventually. Now, I could have used the first version here and just called retain on it as well.
You have a fundamental misunderstanding of allocations versus instance methods.
The first example, NSDictionary's -objectForKey method, returns id, not an instance of NSDictionary, therefore it does not allocate or initialize the variable.
The second, however is the classic retain part of the retain-release cycle.
The two methods are fundamentally equal (if we are to assume that array is alloc'd but empty in the first, and nil in the second), and both get ownership of the array object. I would go with the second, as it guarantees a reference, and it's shorter.
What I think you're confusing this with are new and convenience methods. Convenience methods (like NSNumber's +numberWithInt:, NSString's +stringWithFormat:, and NSMutableArray's +array), return an autorelease instance of the class (usually). New takes the place of alloc and init in just one word.

Retain/release of returned objects

I am new to Objective-C, so this might be a dumb question.
I cannot help but see the similarities between ObjC and Microsoft's COM with respect to memory management (AddRef/Release vs retain/release). In a COM environment, it's more or less imposed on you to always AddRef (retain) an object before returning it to the caller. From what I've seen so far (I'm a third through Cocoa® Programming for Mac® OS X (3rd Edition)), the memory management part is somewhat fuzzy.
Assuming there is no GC, what is the idiomatic way to return an object?
Read Memory Management Programming Guide about autorelease pools.
In Objective-C, by convention, objects should be returned autoreleased (unless the method returning the object has a name that begins with “alloc”, “new”, “copy”, or “mutableCopy”). Autoreleased objects are tracked by Objective-C in a pool and automatically handled, which means you don't need to care about sending a final release to them. This greatly simplifies reference counting compared to COM, and this is why you're not seeing any release calls on returned objects most of the time. In contrast, the same convention specifies that all objects returned by a method whose name begins with alloc, new, copy, or mutableCopy, are the responsibility of the method caller. You have to manually call release on these objects or your program will have memory leaks.
Cocoa goes around the limitations of AddRef/Release in COM by introducing a third sibling; autorelease.
retain - I need this, make it stick around.
release - I don't need this anymore, you may remove it immediately.
autorelease - I don't need this, but let it stay around a few seconds in case someone else wants to pick it up first.
This tiny addition allow most return values to be handles as-if we had garbage collection. If you are not interested in keeping the return value around, just do nothing extra.
In order to get this to work there is a convention (a convention good enough to let the compiler do the memory stuff automatically for you with upcoming ARC):
Method names beginning with these must return retained instances:
alloc
copy
new
retain
All other must return autoreleased instances.
Three example implementation for how this can be applied in practice:
-(NSString*)newHelloWorldString {
NSString* s = [NSString stringWithString:#"Hello world"];
// Apply retain because s in now autoreleased
return [s retain];
}
-(NSString*)helloWorldString {
NSString* s = [[NSString alloc] initWithString:#"Hello world"];
// Apply autorelease because s is now retained.
return [s autorelease];
}
-(NSString*)fullName {
// No memory management needed, everything is autoreleased and good.
NSString* fn = [self firstName];
NSString* ln = [self lastName];
NSString* s = [NSString stringWithFormat:#"%# %#", fn, ln];
return s;
}
Generally something like
return [object autorelease];
and you can retain on the other end.
If you are planning to deploy on Lion/iOS5 or are using the latest SDK then also check out ARC.
Essentially i would recommend making the class that receives it retain it. i.e class stackoverflow receives object answer.
i.e
-(void) setAnswer:(Answer*) _answer{
self.answer = _answer; // If the answer is created from a returned message.
[_answer release];
}
edit: I think I might have put up the wrong stuff up there now that i am looking at it the 2nd time . Meant something along the lines:
Answer *_answer = [stackoverflow createAnswer];
self.answer = _answer;
[_answer release];
If you return an object , it is up to the owner to retain it , i would avoid autoreleases wherever possible because once the nspool kicks in, those objects are gone and if they are still used, it will cause problems.
i.e Answer *answer = [stackoverflow getAnswer] and if answer was created in the getanswer method then whomever is retrieving it is responsible in releasing it.
Makes sense?

How are #"Strings" allocated in memory?

I am curious of the memory allocation for the following code.
NSString *myString = [NSString string];
I know this will create an autoreleased empty string, #""
What happens when I then call
myString = #"Hello world";
Is my reference the same as the autoreleased object NSString provided or did I just allocate a new object that I am responsible for releasing?
When wondering whether you own an object, ask yourself:
Does the method I used to create this object...
begin with new?
begin with alloc?
contain copy?
equal retain?
If you can answer "Yes" to any of those, then you are responsible for invoking release or autorelease on the returned object. (Note that the rules for Core Foundation objects are slightly different. Also note that anything that the documentation explicitly says that contradicts this wins. The documentation always supersedes the guidelines)
In the case of your string, the answers to all your questions are "no", so you are not responsible for the object. Constant strings (of the style #"foo") are hard-coded into the application binary and cannot be deallocated. That, however, is an implementation detail. As long as you follow the memory management rules, you'll be good!

What does "Leak of returned object" mean, from Clang?

Further to this question I've fixed a bunch of memory leaks in BEncoding.m (originally from here)
I've fixed all the obvious memory leaks, but Clang has found four "Leak of returned object" bugs, which I'm not sure how to sort:
The full messages/appropriate bits of code are:
NSMutableData *data = [[NSMutableData alloc] init];
[1] Method returns an Objective-C object with a +1 retain count (owning reference)
[...]
snprintf(buffer, 32, "%lu:", [object length]);
[data appendBytes:buffer length:strlen(buffer)];
[data appendData:object];
return data;
[3] Object returned to caller as an owning reference (single retain count transferred to caller)
you want:
return [data autorelease];
since you're handing it to the caller.
OK, so to expand the answer above (thanks for setting me on the right track) ...
return [data autorelease]
You have allocated some object, "data", and are about to return this object back to the caller. The way this works in Obj-C is that at some level up the call stack, there is an NSAutoreleasePool. When you send the "autorelease" message to data, it adds itself to that autorelease pool. This allows the caller to use the "data" object briefly (ie, over the duration of the local stack frame) without needing to call "release" explicitly, and eventually, when the autorelease pool "pops", data will be deallocated (unless someone calls "retain"). That's rather clever.
Sweet. I think I just earned my green belt in Obj-C memory management.
It sounds like the objects aren't being properly autoreleased before they're returned, which violates the Objective-C memory management conventions.