Nonatomatic assign and memory leak issue - ios

I have one property say
#property(nonatomic,assign) NSString *str;
Now I am having something like
self.str = [[NSString alloc] init];
self.str = #"test";
NSLog(#"%#",str);
[self.str release];
When I run I can see a leak "Potential leak of memory".
Why its showing me leak ?
Please guide me I am leaning phase of iOS

In other words (I'm just expanding on Anoop's answer here), you have two strings, not one.
self.str = [[NSString alloc] init];
self.str = #"test";
The thing on the right side of the first line is a string: [[NSString alloc] init]. But in the second line you throw it away, replacing it with a different string, namely #"test". Now there is NO REFERENCE pointing to the first string. Thus it leaks, since it can never be released nor can anything else ever be done to or for it.
The situation of the string created in the first line is, after the second line, like the situation of "thing1" in the second panel of this diagram:
No one is pointing to it, so its memory cannot be managed, and it lives forever in isolation (leak).

self.str = [[NSString alloc] init]; //1st
One string is allocated not used.
self.str = #"test"; // 2nd
Another constant string "test" is allocated but released.
So first one is a leak.

When you use factory method or create object using alloc,new,retain,copy,mutableCopy your object has +1 retain count every time. You own object in this case. You are responsible for releasing it. So you need to release object after you finish using object which cause -1 retain count to object.
It is not necessary to alloc you string again as you are already creating its property.
And it has its getter setter + you are allocating it again so gives you a leak.

Related

Why retainCount returns 2 [duplicate]

This question already has answers here:
When to use -retainCount?
(11 answers)
Why retain count in negative value? [duplicate]
(1 answer)
Closed 10 years ago.
I have property:
#property(nonatomic, retain) NSMutableArray *myvar;
First case:
myvar = [[NSMutableArray alloc] init];
NSLog(#retainCount: %i:", [myvar retainCount]);
outputs:
retainCount: 1
Second case:
self.myvar = [[NSMutableArray alloc] init];
NSLog(#retainCount: %i:", [self.myvar retainCount]);
outputs:
retainCount: 2
My question is: why in the second case retain value is 2 ?
The only valid answer: never check, use, trust retainCount. it is not meant for debugging or use directly for memory management.
useful: whentouseretaincount.com
But in your case: As you are not using ARC (otherwise the compile wouldnt allow you to use retainCount anyway) you are over retaining.
it retain here #property(nonatomic, retain) NSMutableArray *myvar;
and here: self.myvar = [[NSMutableArray alloc] init];
do:
self.myvar = [[[NSMutableArray alloc] init] autorelease]; //will release once soon
or my favorite, as independent from ARC/MRC and short
self.myvar = [NSMutableArray array]; // identical to the first example
or more explicit
NSMutableArray *var = [[NSMutableArray alloc] init];
self.myvar = var;
[var release];
+1 because you alloc/init'd it
+1 because self.myvar retains it (as set out in your property declaration)
if you autorelease after alloc/init, it will go back down to 1... then if you set self.myvar to nil, it will hit 0 (if nothing else has retained it in the meantime)
But as vikingosegundo has said, you don't want to be messing with retain counts. The OS determines when to knock them back down, so you can't use them as a reliable measure of state.
Here's a rule that I used to go by before ARC came along:
'The NARC rule':
If you use New, Alloc, Retain or Copy, increase the count by one.
Your retain count is 2 in the second case because you are using alloc and retain on the instance property of the class (by using the self keyword). In the other case you are not using the synthesized setter to set the variable, and therefore not using retain. Explore what properties actually do for increased understanding.
vikingosegundo has explained well the correct way to do things in his answer.
Hope that helps!
See this answer: Question About Retain Counts & initializing member variables
First, you alloc init a new NSArray object. That's a retain count of
1. Second, your setter sends the object a retain message when assigning it to your instance var. That bumps the retain count up to
2.
Cheers.

EXC_BAD_ACCESS error when changing views with PresentModalViewController

I'm trying to switch views in my app using this chunk of code:
self->variable1 = [[NSNumber alloc] initWithInt:0];
self->variable2 = [[NSMutableArray arrayWithCapacity:1];
self->variable3 = [[NSMutableArray arrayWithCapacity:1];
[self presentModalViewController:titleScreen animated:YES];
If I comment out all of the allocated variable lines, the code works fine. If it leave just 1 line in the code crashes with the "EXC_BAD_ACCESS" error. Why is this happening? The variables aren't being used at all, just declared for later use. I'm not getting any compile errors on the lines either. What am I doing wrong?
UPDATE:
Thank you everyone for the help. I change the way I declare my variables to #property/#synth to clean up my code, but it didn't fix the problem. After a long time of fiddling I fixed it. I changed the code from this:
self.variable1 = [[NSNumber alloc] initWithInt:0];
to this:
self.variable1 = [NSNumber alloc];
[self.variable1 initWithInt:0];
and it worked! Can someone explain why this worked and the first line didn't?
Update:
Thank you Peter Hosey for showing me my evil ways. This time I'm pretty sure it's fixed. I was storing my variable Releases in
-(void)release
I didn't realize xCode will release when it needs to. I moved all the variable releases to
-(void)Destroy
so I can release everything on MY command. Now the code works. Thanks again!
I suggest that you declare variable1, variable2, and variable3 as properties, not instance variables. Then, use self.variable1, self.variable2, and self.variable3 to access them.
The dot syntax (self.variable1, etc.) uses the memory management policy you declared on each property; the arrow syntax (self->variable1, etc.) will access the variables directly. The crash is because you created two arrays in away that doesn't leave you owning them, and then did not assign the arrays to a property that would retain them.
You may also want to upgrade your project to use ARC. Then there is no memory-management difference; assigning to the instance variables rather than the properties will not cause the object to be prematurely released, because ARC considers instance variables to be ownerships by default. You may still want to switch to using properties after you switch to ARC, but not to prevent a crash.
In response to your edit:
I change the way I declare my variables to #property/#synth to clean up my code, but it didn't fix the problem.
Then something else was wrong.
You never did say much about the problem itself. You said you got an EXC_BAD_ACCESS, but not what statement triggered the crash or on what grounds you blamed it on the code you showed.
I changed the code from this:
self.variable1 = [[NSNumber alloc] initWithInt:0];
That's the correct code, though. That's what you should be using.
to this:
self.variable1 = [NSNumber alloc];
[self.variable1 initWithInt:0];
Noooo! That code is wrong, wrong, wrong, on multiple levels.
init methods (including initWithWhatever: methods) are not guaranteed to return the same object you sent the message to. NSNumber's initWithInt: very probably doesn't.
That object creates an uninitialized NSNumber object and assigns that to the property. Then it sends initWithInt: to that object, which will return an initialized object, which can be and very probably will be a different object. Now you are holding an uninitialized object (which you will try to use later) and have dropped the initialized object on the floor.
Never, ever, ever send alloc and init(With…) in separate expressions. Always send them in the same expression. No exceptions. Otherwise, you risk holding the uninitialized object rather than the initialized object. In your case (with NSNumbers), that is almost certainly what will happen.
What you should be doing is declaring and synthesizing a strong property that owns the NSNumber object, and creating the NSNumber object in a single statement: either [[NSNumber alloc] initWithInt:] or [NSNumber numberWithInt:]. If you're not using ARC, you'll want the latter, since the property will retain the object. If you are using ARC, they're effectively equivalent.
And if you get a crash with that code, then something else is wrong, so please tell us—either in this question or in a new question—about the crash so we can help you find the true cause of it.
variable2 and variable3 are being autoreleased before you actually access them (presumably) later after presenting the modal view.
At the very least change the lines to:
self->variable2 = [[NSMutableArray arrayWithCapacity:1] retain];
self->variable3 = [[NSMutableArray arrayWithCapacity:1] retain];
or
self->variable2 = [[NSMutableArray alloc] initWithCapacity:1];
self->variable3 = [[NSMutableArray alloc] initWithCapacity:1];
variable1 should be fine.
Best would be to use #property and #synthesize so you can use dot notation:
.h
#interface MyClass : SuperClass
#property (nonatomic,retain) NSMutableArray *variable2;
#property (nonatomic,retain) NSMutableArray *variable3;
#end
.m
#implementation MyClass
#synthesize variable2,varible3;
- (void)foo {
self.variable2 = [NSMutableArray arrayWithCapacity:1];
self.variable3 = [NSMutableArray arrayWithCapacity:1];
}
#end
By default, all instance variables in objective-c have protected scope. So unless you have explicitly declared them public in your interface file as:
#interface MYClass {
#public
NSNumber *variable1;
NSMutableArray *variable2;
NSMutableArray *variable3;
}
//...
#end
then they will not be accessible using the struct dereferencing operator. This is likely the cause of those EXC_BAD_ACCESS errors.

What is difference between initilizing an NSString simply and with retain?

I want to know that difference between following two lines
name1 = [[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement,1)] retain];
name1 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement,1)];
What will be effect on name1 if I do use retain at the last,
I face once problem, and couldn't use name1 in a method that is being call by NSTimer, and when I use retain, they it worked fine for me.
If I do call value from database in viewDidLoad, and use in a method that is being called by NSTimer after each second, then it will give bad-exec, but when I do use retain then it will work properly,
I want to know the reason
Here is the difference
- (void)func1 {
name1 = [[NSString stringWithUTF8String:...] retain];
name2 = [NSString stringWithUTF8String:...];
}
- (void)func2 {
NSLog(#"%#", name1); //OK, name1 is still there
NSLog(#"%#", name2); //Would be crashed because name2 could be released anytime after func1 is finished.
}
I wrote this answer to another question, but it explains what you're asking:
Objects in objective c have a retain count. If this retain count is greater that 0 when the object goes out of scope (when you stop using it), it leaks.
The following things increase the retain count
[[alloc] init]
new
copy
[retain]
adding an object to an array
adding an object as a child (e.g. views)
There are likely more, but you don't appear to use any others in your code
The following decrease the retain count
[release]
removing an object from an array
if you dealloc an array, all of its objects are released
You should go through your code and ensure each of the retains or additions to an array are matched with a corresponding release. (You can release member variables in the dealloc method).
Another user made a valid point that my answer doesn't
Once you add an object to an array, it takes ownership and will release the object when it is done with it. All you need to do is make sure you release anything you own according to the memory management rules
There are also autorelease objects, have a look at this example;
-(init){
...
stagePickerArray = [[NSMutableArray alloc] init];
for (int i = 0; i < 3; i++)
{
//this string is autoreleased, you don't have call release on it.
//methods with the format [CLASS CLASSwithsomething] tend to be autorelease
NSString *s = [NSString stringWithFormat:#"%d", i);
[stagePickerArray addObject:s];
}
...
}
Your issue is that when you come to use your string later, it has a retain count of zero and has been released. By calling retain on it, you're saying 'I want to use this later'. Don't forget to match every retain with a release or you're objects will 'leak'
I bet your code wouldn't crash if your name1 was a property - either (nonatomic, retain) or just (copy) depending on your needs.
Second condition is to have name1 initialized to sth meaningful at the time your other function tries to do sth with it.
EDIT:
With a property you'd have to use synthesized setter in this case with: self.name1 = #"your string";.
Normally you don't have to manually retain/release a string created with stringWith... methods since there's nothing you created in memory yourself by using explicit alloc. Also please note that with code:
NSString *str = [NSString stringWithUTF8String:#"your string"];
your str (if not used to set a property) will stop being available when the function gets out of scope (iOS eventloop will autorelease it).

Need clarification in iPhone memory management

I need few clarification in iPhone memory management.
Here is an example for setters;
1).
-(void)setValue:(NSString*)input{
[value autorelease];
value = [input retain];
}
In this example, why we have to use autorelease?
Can we use like as follows?
if(value)
[value release];
value = [input retain];
In the first example, Why we should not release the memory for input
2).
If I use following statement; what is the retain count for value
NSString *value;
value = #"welcome";
After the above statement, just I am trying to set one more value. Then what will happen?
eg:
value = #"For testing";
3).
What is the different between 2) and 3)?
NSString *value;
value = [input1 retain];
...
...
value = [input2 retain];// Now what is the retain count for value
4).
If I use following statement, why the app is getting crash?
NSString *value = [[[NSString alloc] init] autorelease];
...
...
Thanks in advance..
If "input" is the exact same object as "value" then calling [value release] could dealloc the object. So you must retain the new input value, release the old value, then assign the new value to the ivar:
[input retain];
[value release];
value = input;
After each of 2) and 3), the NSString *value points to a literal NSString object, the retain count will be 1 in each case, and releasing it is probably not a good idea
After this code:
value = [input2 retain];
value is an alias to the input2 object. The thing to realize is that objects have retain counts, variables do not.
As for your last case,
NSString *value = [[[NSString alloc] init] autorelease];
It creates an autoreleased empty string. If you reference that object again once the autorelease actually happens, you may get a crash because you'll be referring to an object that doesn't exist any more.
If you release a value before you retain the new value then you can have problems if the same value is being set twice. This happens if the caller hasn't retained their own copy, such as when they get the value from the same object they try to set it on, like this:
object.value = object.value;
That statement will cause the object to be released before it's retained again which could lead to the memory being deallocated and result in a dangling pointer being retained. By doing the autorelease it ensures that copying the same pointer onto itself will work correctly.
I usually write my setters as
- (void)setValue:(NString *)input {
if (value != input) {
[value release];
value = [input retain];
}
}
which avoids the problem of input and value both being the same object. If you just release it without checking then you might completely free it and the next line will try to retain an object that doesn't exist anymore.
However, it's best practice to copy strings instead of retaining them :)
(assuming you're working in a non-gc env)
1) you can create a temporary variable and release the temp after the retain/assign. otherwise, you'd need to compare the pointers. deferred release may also mask threading errors (whether you consider that good or bad is...)
2) technically, the NSString literals are valid for the life of your program. that is: while (1) [#"why won't i die?" release]; yields an infinite loop.
3) with explicit retain, alloc+init, new, and copy, you must counterbalance the retain count using release or autorelease. since you did not release value1, the static analysis may (correctly) spot that as a leak. since the string constants never die, the two aren't comparable in this regard.
4) there's nothing wrong with that staement. the problem lies elsewhere in your program. either you are assigning it to an ivar without retaining, or releasing it later.
try using static analysis often, and try reducing how much you use autorelease (you can't avoid it entirely).
none of this is magic, but you can at least reduce the location of many problems to the callsites (or very close) by not using autorelease all over the place. just use manual retain/release where possible.
lastly, check for leaks and run with NSZombies enabled.
1)
You will have to do autorelease because of the following:
When input is the same object as value and you will release value it's retain count will reach zero and get deallocated before you can retain it again though the input.
You can do it with retain but you have to change your code:
-(void)setValue:(NSString*)input{
if (value != input) {
[value autorelease];
value = [input retain];
}
}
2)
I believe #"Text" will be treated as a constant. When you want a object which you do not want any memory management with use:
NSString *value = [NSString stringWithString:#"Text"];
This will return an autoreleased object.
3) In this example it is not about the retain count of value, but about the retain count of both objects where value one is referenced to.
When you dont release input1 before you leave that method, you will have a memory management problem.
4) This statement should work. No points to argue. You rather use [NSString string].
Note:
For memory management: when you use alloc new or copy, you also have to use release or autorelease on the same object in the same scope.

Objective C NSString* property retain count oddity

I have the following example class:
Test.h:
#interface Test : UIButton {
NSString *value;
}
- (id)initWithValue:(NSString *)newValue;
#property(copy) NSString *value;
Test.m:
#implementation Test
#synthesize value;
- (id)initWithValue:(NSString *)newValue {
[super init];
NSLog(#"before nil value has retain count of %d", [value retainCount]);
value = nil;
NSLog(#"on nil value has retain count of %d", [value retainCount]);
value = newValue;
NSLog(#"after init value has retain count of %d", [value retainCount]);
return self;
}
Which produces the following output:
2008-12-31 09:31:41.755 Concentration[18604:20b] before nil value has retain count of 0
2008-12-31 09:31:41.756 Concentration[18604:20b] on nil value has retain count of 0
2008-12-31 09:31:41.757 Concentration[18604:20b] after init value has retain count of 2147483647
I am calling it like:
Test *test = [[Test alloc] initWithValue:#"some text"];
Shouldn't value have a retain count of 1? What am I missing?
Thanks for your help.
Don't look at retain counts. They're not useful and will only mislead you — you can't be certain that nothing else is retaining an object, that an object you get from somewhere isn't shared.
Instead, concentrate on object ownership and follow the Cocoa memory management rules to the letter. That way your memory management will be correct no matter what optimizations Cocoa may be doing behind the scenes for you. (For example, implementing -copy as just -retain for immutable objects.)
Furthermore, it's critical to understand the difference between properties of your objects and instance variables within your objects. In your question's code, you are assigning a value to an instance variable. That instance variable is just that: a variable. Assigning to it will behave like any other variable assignment. To use the property, you must use either dot syntax or bracket syntax to actually invoke the property's setter method:
self.value = newValue; // this is exactly equivalent to the next line
[self setValue:newValue]; // this is exactly equivalent to the previous line
The code generated for the dot syntax and the bracket syntax is identical, and neither will access the instance variable directly.
You are passing in a literal string. The compiler probably allocates it in static memory and sets the retain count to the maximum possible value.
Try a dynamically allocated string instead and see what happens.
NSString* string = [[NSString alloc] initWithString: #"some text"];
Test* test = [[Test alloc] initWithValue: string];
You've got a reference to an immutable string. Assignment doesn't need to copy the value (the string data) since it's immutable. If you do a mutable operation, like value = [newValue uppercaseString] then it should copy the bits into value, and value's retain count incremented.
You're passing in a string constant, which can't really be deallocated. I think that 2147483647 is probably UINT_MAX, which basically means that the object can't be released.
I think you want to do this:
self.value = newValue;
which will invoke the property setter and cause the copy to occur. "value = newValue" simply assigns a pointer value to the instance variable.
You shouldn't be paying attention to the retain counts, just follow the Cocoa memory management rules. http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html
hmm.. we're getting closer.
it appears that newValue's retain count is also 2147483647.
I tried dynamically allocating the string instead with the same retain count results.
I found a helpful article here: http://www.cocoadev.com/index.pl?NSString
FTA:
Does the NSString returned by #"" need to be released, or is it autoreleased?
Neither. #""-strings are of class NSConstantString?, and thus act like atoms in lisp; they hang around. That is, if you use #"cow" in two separate places in your code, they will be referencing the very same object.
I don't think -release or -autorelease does anything to either of them.
If I have "copy" on the property though, shouldn't it copy the contents of the target memory into new memory with a retain count of 1? It would seem the copy attribute does nothing in this case?
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
char *cstr = "this is a c string";
NSString *str = [[NSString alloc] initWithUTF8String:cstr];
NSLog(#"rc1: %d", [str retainCount]);
[pool drain];
return 0;
}
If you run the above code, it will display a retain count of 1
In Cocoa, many immutable objects will simply retain themselves when you ask for a copy within the same zone. If the object is guaranteed not to change (i.e. its immutableness) then an exact duplicate is redundant.
In Objective-C, the constant string class is separate to Cocoa's NSString class, although it may be a subclass of NSString (I'm not too sure). This constant string class may override NSObject's methods like retain, release and dealloc so that they do nothing, and also override retainCount so that it always returns the same number, UINT_MAX or so. This is because an Objective-C constant string is created in static memory. It must have the overall general behaviour of a Cocoa object (when using Cocoa) so that it can be added to arrays, used as keys to a dictionary etc, except in regards to its memory management, since it was allocated differently.
Disclaimer: I don't actually know what I'm talking about.

Resources