In my iOS app ARC is disabled. I find some memory leak issues in my code when i inspect my code using instrument tool, it is described bellow.
Obj1 is a an object that declared in the .h file (its type is classA).
I set the value of Obj1 in .m file using the code:
self.Obj1 = [[classA alloc]init];
I release Obj1 in the dealloc method.
this code works fine. but shows a memory leak issue.
How can i avoid this memory leak issue.??
Use below code :
self.Obj1 = [[[classA alloc]init]autorelease];
Dealloc will only be called when the view is not in use or unload.
If you use NSZombieEnabled macros for handling work with released objects all objects (even released) will have at least 1 retain count and tools will show all object as "leaking". Just turn off this macro when you work with memory leaks.
See technote for references:
https://developer.apple.com/library/ios/technotes/tn2239/_index.html
If you make a property retain Obj1 means increment by 1 then after you alloc this object by increment 1, so it's value retain 2.
Use below code:
ClassA *objC = [[classA alloc]init];
self.Obj1 = objC;
[objC release];
There are many ways to handle this :
First,
self.Obj1 = [[[classA alloc]init]autorelease];
Second,
Obj1 = [[classA alloc]init];
...
// use self.Obj1 in the code
...
[Obj1 release];
Third,
self.Obj1 = [[classA alloc]init];
...
[self.Obj1 release];
Use any one out of these.
You can remove self., just Obj1 = [[classA alloc]init];.
Because when you call self.,you retain the object again.So after self.Obj1 = [[classA alloc]init];,object retain count is 2.
Related
Is there a difference between the initializations [NSArray new] and [NSArray array]?
array seems to be part of the implementation of NSArray while new belongs to NSObject.
new = alloc + init
This method is a combination of alloc and init. Like alloc, it
initializes the isa instance variable of the new object so it points
to the class data structure. It then invokes the init method to
complete the initialization process.
NSObject Class Reference
+new is implemented quite literally as:
+ (id) new
{
return [[self alloc] init];
}
and new doesn't support custom initializers (like initWithObjects), so alloc + init is more explicit than new
So the question now is about:
[NSArray array] vs [[NSArray alloc] init]
The main difference between these is if you're not using ARC
(Automatic Reference Counting). The first one returns a retained and
autoreleased object. The second one returns an object that is only
retained. So in the first case, you would want to retain it if you
wanted to keep it around for longer than the current run loop. In the
second case, you would want to release or autorelease it if you didn't
want to keep it around.
Now that we have ARC, this changes things. Basically, in ARC code, it
doesn't matter which of these you use.
But keep in mind that [NSArray array] returns an empty immutable array, so using array with NSMutableArray makes more sense
For more information:
alloc, init, and new in Objective-C
Use of alloc init instead of new
Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]
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.
my.h file
#interface myObject : NSObject {
NSMutableDictionary *myDictn ;
}
i have a property
#property (nonatomic,retain) NSMutableDictionary *myDictn ;
then in .m File
i have a allocated it from id
- (id)init {
if (self=[super init]) {
myDictn= [NSMutableDictionary alloc]init];
}
}
my Question is i have mentioned Retain in Property and i have allocated memory also (is Retain Count goes to 2 in (id)init )
so how to manage memory in this case ?
i am new to this so dnt have much idea regarding memory management .
one more thing if i have a method x in my code and i also allocated memory to myDictn then in that case also how can i use release .??
Thanks in Advance .
The proper way to initialize a retained property is:
NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
self.myDictn = newDict;
[newDict release];
or alternatively:
self.myDict = [NSMutableDictionary dictionary];
The first method makes sure not to increase the already retained property's retain count by performing alloc,init (an action that increments retain count) on a temporary object.
The second method uses a convenience method for obtaining an autoreleased instance of the dictionary.
You should first refer to Cocoa Fundamentals Guide. Then, if you're targeting iOS > 4.3, you can rely on Automatic Reference Counting for memory management. But be sure to understand the base concepts and read the fundamental guide or you'll waste a lot of time programming in the dark.
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.
Why would I use (inside my dealloc method)?
[myInstance release] instead of [self.myInstance release]
myInstance = nil instead of self.myInstance = nil
Although we use self.myInstance = [[[AClass alloc] init] autorelease] instead of myInstance = [[[AClass alloc] init] autorelease]?
Those practices are from numerous examples I see on the web.
1) [myInstance release] instead of [self.myInstance release]
prefer the former.
the returned value of self.myInstance is defined by implementation when a subclass has overridden the method myInstance. you're not interested in the behaviour of the interface of a constructed object during dealloc (since a subclass may override and return something other than your ivar).
what you are interested in dealloc is releasing the references you own before your object is destroyed. if the subclass has overridden myInstance, then it could:
a) return an ivar (declared in the subclass) that's already been released
or
b) the implementation of the override may return a newly created autoreleased object
either a or b could lead to an over-release and a crash (assuming everything else is correctly retained/released). this also suggests why you should assign nil to the ivar after releasing it.
this is also a classic example of how to trigger object resurrection. object resurrection occurs when an implementation of the getter/setter you call recreates its state after it's already been deallocated. the least offensive side-effect would cause a harmless leak.
2) myInstance = nil instead of self.myInstance = nil
again, prefer the former.
a formal response would look much like the response to #1 -- the rationale, side-effects and dangers apply here as well.
the safest way to handle this is to access the ivar directly:
[myInstance release], myInstance = nil;
because there may be really nasty side-effects (crashes, leaks, resurrection) which may be difficult to reproduce.
these dangers may be easily avoided and your code will be far easier to maintain. on the other hand, if people encounter the side-effects when using your programs, they will probably avoid (re)using it wherever they can.
good luck
Calling self.myInstance = uses the auto generated setter method. Calling [self.myInstance release]; calls release on the object returned by your getter method. It all depends on how your properties were set up (retain, assign?). There is no necessarily right or wrong answer to your question, since it all depends on the property in question. I suggest you read up on Objective C properties to get a better feel for this kind of thing.
And, unless myInstance was declared with assign, you wouldn't want to call self.myInstance = [[AClass alloc] init] You'd be much better off with self.myInstance = [[[AClass alloc] init] autorelease]
Note that using
myInstance = nil
instead of
self.myInstance = nil
Is incorrect (in the context of say a viewDidUnload method in a UIViewController subclass) if myInstance is a retain property, since if myInstance points to an object, it will be leaked!
This depends on a property that you defined in interface. For example if you define retain property:
#property (nonatomic, retain) NSObject *property;
then you may use just self.property = nil; in dealloc method, because it equals to:
[property release]; // releases previous property
property = [nil retain]; // [nil retain] returns just nil
The very same thing with self.property = [[A alloc] init];. This equals to
[property release]; // releases previous property
property = [[[A alloc] init] retain];
in case of property = [[A alloc] init]; property won't be retained.
Here's a full properties guide form Apple.
Actually using
self.myInstance = [[AClass alloc] init];
will lead in a memory leak, cause self.myInstance is using setter methods which leads in retain +1 along with alloc/init retain +1. So you'll get a retain count +2;
... = self.myInstance
and
self.myInstance = ...
are actually subroutine or method calls to getters and setters, which depending on how you define these subroutines, or have Objective C Properties create them, could do almost anything.
If the case of retain properties, the subroutines might play with the retain counts. If you do your own getters and setters, you could have them control the lights in your house, turning them on for none zero sets and turning the lights out when setting something to zero or nil. There doesn't even need to be a backing variable named "instance" which could be set by:
instance = ...