Need advice about memory management - objective-c

I have been working with Objective-C for a month approximately but regretfully I'm still a complete dummy in memory management so I need your advice. I pass an array from one file to the other like this
BidView *bidView = [[[BidView alloc] init] autorelease];
NSLog(#"%i",[bidView.seatsForTableCreated retainCount]);
bidView.seatsForTableCreated = [NSArray arrayWithArray:seats];
NSLog(#"%i",[bidView.seatsForTableCreated retainCount]);
[self.navigationController pushViewController:bidView animated:YES]; `
NSLog tells me that retain count of seatsForTableCreated has raised from zero to two. Then, when I quit the BidView screen (without doing anything with seatsForTableCreated array) I' m doing the following:
NSLog(#"%i",[seatsForTableCreated retainCount]);
[seatsForTableCreated release];
NSLog(#"%i",[seatsForTableCreated retainCount]);
it's quite unclear for me. Now NSLog tells me (both times) that retain count is 1. Then I repeat this procedure (running the same application I mean) and each time things are the same:0-2-1-1. So my questions are:
1)Why 0 to 2? Why retain count increases to 2 not to 1?
2)why then it drops to 1 without being impacted in any way?
3)Why it still remains 1 after i've released it?
4)How would you manage the memory in such a case?
Great thanks in advance

First and foremost. Don't call nor use retainCount for nothing, think about this property as private and only the OS can call. To check if you have a memory leak you should use Instruments.
Seems like you've created an autoreleasing ([NSArray arrayWithArray:seats]) object, so you can't manually release it.
And use the Allocations Instrument to really check if you have a memory leak.

My advice assumes you are using Xcode 4+ and you are not using ARC,
command+shift+B will analyse your memory management (and dead stores and such). I think you got it right. Don't worry about the retain counts so much until you get a complaint from Analyze or find leaks with Instruments. I am not sure how reliable retain counts are. I have seen comments on SO saying not to rely on them.
You are following the rules well
New, Alloc, Copy, Retain --> You will need to release this object when you are done with it.
I am also assuming in BidView.h your property is declared as
#property(nonatomic, retain) NSArray * seatsForTableCreated;
So releasing that in the dealloc method in BidView.m is good memory management
EDIT
It works when even though you don't allocate seats for table created because.
self.seatsForTableCreated = ... will retain whatever object you are setting there.
So if you have a property with (retain) in the declaration, you can consider
self.property = object;
as setting property and retaining it. The properties were added to objective-C to reduce similar code being in every class.
A property in .h
#property (nonatomic,retain) NSObject * property; // don't name your properties property..
Compiler will create 2 methods for you automatically when you #synthesize in the .m
-(void)setProperty:(NSObject*)newP
{
[newP retain]; // retains the new object so it sticks around for line 3
[property release]; // releases previous property
property = newP; // set the property to the object retained in line 1
// property is now same as newP and you are responsible for releasing it
// -(void) dealloc is where you should release it
}
// Note, the compiler may not create the exact same code as above when creating the //setProperty method. If it does, it could be subject to change.
-(NSObject*)property
{
return property;
}
I tried to figure out why Analyze isn't catching the issue when you don't release your property, but haven't. That is confusing and I want to explore it further.

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)

Using objects I didn't allocate or initialize

I just wrote some code. It has my own custom made class. In that custom made class called 'WonderfulNumbers' I have a method that looks like this
- (NSString *)storedNumberAsString {
NSString *stringToReturn = [[NSString alloc]initWithFormat:#"Hello World"];
return [stringToReturn autorelease];
}
I obviously then #import "WonderfulNumbers" into the main and etc
then in my main I have an IBAction.
it reads like the following
-(IBAction)displaySomeText:(id)sender {
WonderfulNumbers *myNumber = [[WonderfulNumbers alloc]init];// Step 1
NSString *numberString = [myNumber storedNumberAsString];// Step 2
[textView insertText:numberString];// Step 3
//textView is a variable of NSTextView.
[myNumber release];// Step 4
}
I get the step by step process, and the logic behind this.
What I like to know and try to reassure to my self is what exactly is happening at step 2.
I understand Step 1, 3 and 4.
But step 2, I crated an NSString variable called 'numberString' and it obviously holds the object called 'myNumber' with the method described above applied to it. Makes sense.
What I want to know is, I never allocated or initialized the 'numberString' object of NSString class. How am I able to then use it.
I know I don't release it since it's never allocated .. but did I initialize it by just doing [myNumber storedNumberAsString]; ?
A slight explanation would be awesome. Thank's to those that reply.
P.S. I know that everything in objective-c is an object but just for the sake of this argument, since 'numberString' is not technically "created by allocate and init" is it right to call that a variable?
I think I know the differences between the two but just want reassurance.
Thanks.
You are initializing NSString *stringToReturn to the return value of [myNumber storedNumberAsString]. Inside storedNumberAsString you can see that it returns an NSString reference, properly allocated and all, so it's fine to use.
The key here is autorelease, which causes the object to be released automatically “sometime later” (actually when the topmost autorelease pool is released, which, unless you changed it yourself, tends to happen after each iteration of the event loop).
The convention in Objective-C is that if you alloc or retain an object, or get an object from a method whose name begins with new, copy, or mutableCopy, you are responsible for releasing it. Otherwise you can assume it will be released by someone else (e.g., later via autorelease). Since storedNumberAsString does not begin with new, copy, or mutableCopy, you don't need to release it. Meanwhile the implementation of storedNumberAsString must ensure that the object it allocs gets released -- in this case that is done by calling autorelease on it.

Memory Management assigning without allocating directly

Suppose that i have UIView viewLoading declared in .h. and i do not directly initialize it (in the first code).
The first Code.
UIView *viewLoading2 = [[[UIView alloc] initWithFrame:CGRectMake(75 , 155, 170.0, 170.0)]];
viewLoading = viewLoading2;
[viewLoading2 release]
The second code:
viewLoading = [[[UIView alloc] initWithFrame:CGRectMake(75 , 155, 170.0, 170.0)]];
The third Code:
- (void) viewLoad:(UIView *) viewLoading2
{
viewLoading = viewLoading2;
//do i need to retain, alloc, or release something here?
}
2In the first code, do i need to release viewLoading in dealloc ? And what happen if i do not declare its property?
In the second code, does it have same effect from the first code? (need to dealloc or not).
For the third code, does it have same effect from the first code? and what should i do after i code that? (see the comment)
Do iPhone Code always need to have release for variable declared in .h? Or only if the variable declared in .h is allocated? if like in the first code, do i need to dealloc viewLoading?
what is the different between
self.viewloading = viewLoading2;
and
viewloading = viewLoading2;
Thanks
In the first example, you allocated the object (once), and you released it (once), so you don't need to do anything else. On the other hand, viewLoading is invalid as soon as you send the release to viewLoading2, so it's not very useful code.
In the second, you have not released viewLoading yet, so it does need to be done eventually.
In the third, whatever code allocated the object that was passed into this method via the parameter is responsible for releasing it. It should be valid for the duration of this method, but if you're saving it for later use you need to retain it here, then release it when you're done.
Edit:
I'm not sure I understand your question 4. A declaration in the interface (.h) file is just reserving space for a pointer. It's not an object declaration, so there's no release required until you actually do an object allocation.
self.viewloading = viewLoading2 is using the properties setter method to do the assignment. If the #property statement has "retain" in it, then a retain is done as part of that assignment. `viewloading = viewLoading2" is a straight assignment, no retain.

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?

Object allocate and init in Objective C

What is the difference between the following 2 ways to allocate and init an object?
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
and
self.aController= [[AController alloc] init];
Most of the apple example use the first method. Why would you allocate, init and object and then release immediately?
Every object has a reference count. When it goes to 0, the object is deallocated.
Assuming the property was declared as #property (retain):
Your first example, line by line:
The object is created by alloc, it has a reference count of 1.
The object is handed over to self's setAController: method, which sends it a retain message (because the method doesn't know where the object is coming from), incrementing its reference count to 2.
The calling code no longer needs the object itself, so it calls release, decrementing the reference count to 1.
Your second example basically does steps 1 and 2 but not 3, so at the end the object's reference count is 2.
The rule is that if you create an object, you are responsible for releasing it when you're done with it. In your example, the code is done with tempAController after it sets the property. It is the setter method's responsibility to call retain if it needs that object to stick around.
It's important to remember that self.property = foo; in Objective-C is really just shorthand for [self setProperty:foo]; and that the setProperty: method is going to be retaining or copying objects as needed.
If the property was declared #property (copy), then the object would have been copied instead of retained. In the first example, the original object would be released right away; in the second example, the original object's reference count would be 1 even though it should be 0. So you would still want to write your code the same way.
If the property was declared #property (assign), then self isn't claiming ownership of the object, and somebody else needs to retain it. In this case, the first example would be incorrect. These sorts of properties are rare, usually only used for object delegates.
As others have noted, the two code snippets you show are not equivalent (for memory management reasons).
As to why the former is chosen over the latter:
The correct formulation of the latter would be
self.aController= [[[AController alloc] init] autorelease];
Compared with the former, this adds additional overhead through use of the autorelease pool, and in some circumstances will lead to the lifetime of the object being unnecessarily extended (until the autorelease pool is released) which will increase your application's memory footprint.
The other "possible" implementation (depending on where the example is from) is simply:
aController = [[AController alloc] init];
However, setting an instance variable directly is strongly discouraged anywhere other than in an init or dealloc method. Elsewhere you should always use accessor methods.
This brings us then to the implementation shown in sample code:
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
This follows best practice since:
It avoids autorelease;
It makes the memory management semantics immediately clear;
It uses an accessor method to set the instance variable.
Note also that your desire to cut the code down to one line is why many people use Autorelease:
self.aController = [[[AController alloc] init] autorelease];
Though in theory on the iPhone autorelease is somehow more expensive (never heard a clear explanation why) and thus you may want to explicitly release right after you assign the object elsewhere.
If you're using Xcode, it can help you detect such code with the static analyzer.
Just hit Build >> Build and Analyze
This will show you a very helpful message at such pieces of code.
One other thing to note is that your example depends on the #property definition of aController also.
If it were defined as #property (readwrite, retain) id aController; then your example works, while if it is defined as #property (readwrite, assign) id aController; then the extra call to release would cause your object to be deallocated.
You could also do
#property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];
with a retaining property, and it would function the same way, but its better to use the other way (for retaining properties) because it's less confusing, that code makes it look like you assign aController and then it gets deleted from memory, when actually it doesn't because setAController retains it.