Potential memory leak in NSData category - objective-c

When using the XCode analyzer I get a message saying:
Potential leak of an object allocated
The code this is in my NSData(String) category, the code is:
- (NSString*) utf8String
{
return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
}
Now how can I solve this? When I change the statement to:
- (NSString*) utf8String
{
return [[[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding] autorelease];
}
My application crashes on the line where I call utf8String.

The cocoa naming conventions suggest that all methods return autoreleased objects, with the exception of methods whose names start with 'init', 'copy' or 'new'. The static analyzer knows and checks this.
You have two choices. You can rename the method to -newUTF8String, or you can return an autorelease object and retain it when you want to store the return value of this method.
I would prefer the latter, but both would be valid code.

I guess your application crashes because the variable is released before it is used. It is recommended to call retain if you do not use the return value right away but store it in a member variable.
...
myMemberVariable = [something utf8String];
[myMemberVariable retain];
...
To make sure that you do not produce a memory leak you have to release the member variable somewhere. A good place for that would be dealloc.
- (void)dealloc {
if (myMemberVariable) [myMemberVariable release];
[super dealloc];
}
I would also recommend having a look at Advanced Memory Management Programming Guide to get some detailed information about memory management of iOS.

Related

Difference between Strong and Weak references (Using ARC) Please No Theory..I know the difference theoretically

I have been trying to understand the difference between Strong and Weak references in iOS. What I did to understand is:
//.h File
#property(nonatomic,strong) NSString* myStrongString;
#property(nonatomic,weak) NSString* myWeakString;
//.m File
- (void)viewDidLoad
{
[super viewDidLoad];
[self assignTempString];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)assignTempString{
self.myStrongString = [[NSString alloc] initWithString:#"Varun Mehta"];
}
- (IBAction)printAssignedString:(id)sender {
NSLog(#"Object will have strong reference so it will print my name==%#",self.myStrongString);
}
According to my understanding when I repeat the above step by using myWeakString it should print null. But its still printing my name. Anybody having any idea why its happening.
But when I replace [[NSString alloc] initWithString:#"Varun Mehta"] with [NSString stringWithFormat:#"Varun Mehta"] or [[NSString alloc] initWithFormat:#"Varun Mehta"] result is coming as I have expected.
There are several things to consider here.
A statically declared string is built into your app so it isn't really retained or released, thus a weak reference to #"my string" will always be valid. The compiler is just recognizing [[NSString alloc] initWithString:#"Varun Mehta"] as a static string and removing your alloc/init. However anything that deals with formatting is, by definition, creating a new string and thus the new string obeys the weak referencing rules and is immediately deallocated, nil-ing out the reference.
If you access a weakly retained object that ends up in the autorelease pool it won't actually get deallocated until all your methods return and the run loop goes back into another cycle (and thus drains the autorelease pool), so you can continue to work with the object even though it is "walking dead". This is typically only when interacting with non-ARC code.
If you need practise try this code:
- (void)viewDidLoad
{
[super viewDidLoad];
[self assignTempString];
}
-(void)assignTempString{
#autoreleasepool
{
self.myStrongString = [NSString stringWithFormat:#"%#", #"Strong string"];
self.myWeakString = [NSString stringWithFormat:#"%#", #"Weak string"];
}
}
- (IBAction)printAssignedString:(id)sender {
NSLog(#"Strong ptr content: %#",self.myStrongString);
NSLog(#"Weak ptr content: %#",self.myWeakString);
}
[NSString alloc] will allocate an ARC-managed object and will set its retain count to 1. As long as your view controller is alive, this retain count will be 1, so it will not be deallocated. [NSString stringWithFormat:] returns an autoreleased string which is deallocated after the execution of [self assignTempString].
Two methods initWithString and stringWithFormat suggest exactly what is to expect.
So initWithString expects you to create allocate memory and then initialise it.
While stringWithFormat expects you to just point to the string.
When you do a init with your strong/weak variable it will exist till end of your program.
While when you point;
strong literal will keep a reference and hence will not allow ARC to cleanup the string literal,
weak literal will not keep a reference and hence ARC is free to clean it up immediately after the function call.
Hope it clarifies working for you.
What you are experiencing happens because of how NSString is implemented.
Since NSString objects are immutable the compiler takes a shortcut when you use stringWithString: with a string literal as argument. If the argument of this and other related methods is a string literal the returned value will just point to the string literal. The whole object instantiation is optimized away.
And string literals won't be deallocated. But the weak variable is only nil'd out during dealloc, so if dealloc is never called the weak variables are never set to nil.
This won't happen if you use stringWithFormat:. Even using only string literals as argument will create new string instances.
Why? Most likely because Apple decided that it's not worth the effort to check if stringWithFormat: was used with a string literal that does not have any format specifiers.
That's an implementation detail, don't think too long about this decision. It should not influence the code you write. I would suggest you treat every string that is not a bare literal (i.e. #"Foo" without any NSString methods) as dynamically created NSString (i.e. use isEqualToString: for all your string comparisons)
This logging code will show this reuse behaviour. It'll show the same addresses for all NSString instances, because the compiler has optimized all those calls to a simple #"Foo".
NSLog(#"%p", #"Foo");
NSLog(#"%p", [[NSString alloc] initWithString:#"Foo"]);
NSLog(#"%p", [NSString stringWithString:#"Foo"]);
NSLog(#"%p", [[NSString stringWithString:#"Foo"] copy]);
NSLog(#"%p", [#"Foo" copy]);
In newer versions of Xcode you will even get nice warnings for this code:
using initWithString: with a literal is redundant
using stringWithString: with a literal is redundant

Does ARC ever inject unconventional code?

Does ARC ever inject retain and release calls that you generally wouldn't see in a non-ARC environment?
For example, explicitly releasing an object from a getter:
- (NSArray *)dummyArray {
return [[NSArray alloc]init];
}
- (void)useDummyArray {
NSArray * arr = [self dummyArray];
//do something with arr
[arr release]; //unconventional injection of release.
}
Would ARC ever generate a release statement like the code above or would it autorelease the array returned by [self dummyArray];
The beauty of ARC is that you don't know, or need to know. However, you can give hints to the ARC static analyzer:
-(NSArray *) dummyArray NS_RETURNS_RETAINED { // this tells ARC that this function returns a retained value that should be released by the callee
return [[NSArray alloc] init];
}
-(NSArray *) otherDummyArray NS_RETURNS_NOT_RETAINED { // this tells ARC that the function returns a non-retained (autoreleased) value, which should NOT be released by the callee.
return [[NSArray alloc] init];
}
However, NS_RETURNS_NOT_RETAINED is the default, as long as your function name doesn't begin with init, in which NS_RETURNS_RETAINED becomes default.
So, in your specific scenario, it will almost always return an autorelease'd value. One major reason for this is support for interpolation with non-ARC code, which could result in leaks.

Managing Memory in Objective c

I am doing my project in xcode 4.2 (Older Version). For my application, I just set the variables, arrays in dto class for using in entire app lifecycle. so I set with a property like this.
AppDTO(sub class of NSObject)
AppDTO.h
#property(nonatomic,retain)anotherAppDTO *aAppDTO;
#property(nonatomic,retain)NSMutableArray *array1;
#property(nonatomic,retain)NSMutableArray *array2;
#property(nonatomic,retain)NSString *string1,*string2,*string3;
AppDTO.m
- (id)init
{
self = [super init];
if (self) {
self.aAppDTO = [[anotherAppDTO alloc]init];
self.array1 = [[NSMutableArray alloc]init];
self.array2 = [[NSMutableArray alloc]init];
self.string1 = #"Hello";
self.string2= #"Hai";
}
}
-(void)dealloc
{
if(array1 != nil)
{
[array1 release];
array1 = nil;
}
if(array2 != nil)
{
[array2 release];
array2 = nil;
}
[aAppDTO release];
aAppDTO = nil;
[super dealloc];
}
when I analyze my app in Xcode 4.3.2, I get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when I change self.array1 to array1, warning goes away.
What is the reason for using self. do I need to use self if I set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
Also in dealloc method, I heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
Do I need to release my string in dealloc method.
Also I am releasing aAppDTO in dealloc method. if I allocate some objects in anotherAppDTO class, will it release automatically when I call [aAppDTO release] method.
Can anyone clarify me.
Many Thanks,
Anish
You get the warning because when you write :
self.array1 = [[NSMutableArray alloc]init];
is the same as :
[self setArray1: [[NSMutableArray alloc]init]];
As you can notice you are not allocating the underlying array1 private variable, but you are calling the setter of the property that since it is declared as retain it retains the object once assigned, this means that when you eventually will assign another object the second time with the setter the first object will remain with a retain count of one until the application will be closed (since you don't have any reference to that object anymore ...) .
Take a look at this great article to understand better Manual Reference Counting in Objective-C .
when i analyze my app in Xcode 4.3.2, i get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when i change self.array1 to array1, warning goes away.
the analyzer's right. the parameter is retained when set. as well, you should favor direct access in initialization and dealloc. so, you should just write array1 = [[NSMutableArray alloc] init];, and be done.
What is the reason for using self. do i need to use self if i set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
those go through the accessor methods. if not in initialization or dealloc, you should favor going through the accessor methods because that is the common correct execution path for a fully constructed object.
Also in dealloc method, i heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
correct.
Do i need to release my string in dealloc method.
yes.
Also I am releasing aAppDTO in dealloc method. if i allocate some objects in anotherAppDTO class, will it release automatically when i call [aAppDTO release] method.
when its reference count reaches 0, its dealloc will be called.
I think the others have answered your question.
I do want to draw your attention to Apple's excellent Advance Memory Management Programming Guide: Practical Memory Management, in which they walk through these sorts of scenarios. It's hard to take it all in on the first reading, but it really does cover this stuff. In answer to your question about the use of instance variables versus the accessor methods, I draw your attention to the section labeled to "Don't Use Accessor Methods in Initializer Methods and dealloc".

big memory problem in objective c

i've a function like this:
#property(nonatomic,retain) NSMutableArray *array;
#synthesize array = _array;
(NSMutableArray *) name
{
self.array = [[NSMutableArray alloc]init];
[_array addObject:object];
[object release];
return [_array autorelase];
}
In the other function i've a property like the property above, named result, and i make:
self.result = [... name];
Then in dealloc i make
[_result release];
and it crashes in this point, how can i solve this?
I've tried many roads, but or it crashes, or i see memory leak in Instruments, where am i wronging?
Thanks.
While there's a lot wrong with this code, the likely cause of your crash is that you're releasing object within -name without taking ownership of it- unless you're creating object within the method through a call to -alloc, -new, or -copy, that method doesn't own it and isn't responsible for releasing it. This is causing that object to be invalid within the NSMutableArray, so when _result releases, it attempts to release an invalid piece of memory and crashes.
Also, properties aren't simply local variables for individual functions, they're member variables for instances of the class for which you're writing these classes. If your end goal is only to return an autoreleased array and set it to result you could do the following:
- (NSMutableArray *) name {
//call a convenience method- it comes back autoreleased
NSMutableArray* theArray = [NSMutableArray array];
[theArray addObject:object];
//don't release object unless you took ownership of it in this function
return theArray;
}
then outside the function, either call self.result = [... name] or [self setResult:[... name]];
You have a very strange method definition (the header should have a - before the return type), and inside that definition you are accessing a variable called object that doesn't seem to exist. I'm not sure what you want, but you've got at least one memory problem. The array that you create in name gets leaked every time the method is called. If you add some details, like the crash message, someone may be able to help more.

Objective-C memory management: how do you release the memory when you return an allocated instance?

How do you release the memory in this situation? Do you have to?
- (NSString *) whatHappensHere {
NSMutableString * mutableString = [[NSMutableString alloc] initWithString:#"Hello"];
// ....
// more code ...
// ...
return mutableString;
}
With autorelease
- (NSString *) whatHappensHere {
NSMutableString * mutableString = [[NSMutableString alloc] initWithString:#"Hello"];
[mutableString autorelease];
return mutableString;
}
As willcodejavaforfood said, the convention is that any newly-allocated object returned from a method should be autorelease'd before being returned. This tells the Objective-C runtime that if nobody takes ownership of it with retain before (in most cases) the current iteration of the application event loop ends, it should be freed.
If it's just used locally in the calling function or returned up the stack, that works great and it gets freed sooner or later. If someone ends up wanting to keep it around, then they have to retain it and so will know they have to release it themselves later on.
(In fact, most of the non-init* utility constructors for ObjC base classes like strings, etc, do just that, or at least something functionally equivalent.)