In my appDelegate I am using LocationManager :
- (void)locationManager: (CLLocationManager *)manager
didUpdateToLocation: (CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
float latitude = newLocation.coordinate.latitude;
strLatitude = [NSString stringWithFormat:#"%f",latitude];
float longitude = newLocation.coordinate.longitude;
strLongitude = [NSString stringWithFormat:#"%f", longitude];
[self CheckOperation];
}
strLatitude and strLongitude are global strings. This is absolutely fine. Even on analyzing the application I don't get any memory leak. But when I profile my application I receive a memory leak at
strLatitude = [NSString stringWithFormat:#"%f",latitude];
and
strLongitude = [NSString stringWithFormat:#"%f", longitude];
of 32 bytes.
How can I fix that?
Are you sure you're seeing a leak and not simply just an allocation?
If you do actually have a leak here then there are some potential suspects:
Are you using ARC? If not, here are some possible problems:
Are you releasing it in dealloc?
If this method gets run more than once, you aren't releasing the last value before you reassign it.
If you're not using copy semantics, and you're passing this string reference off to someone else, and they aren't properly releasing it, you'll also get a backtrack to this line.
EDIT:
(Per the comments below)
You should realize that stringWithFormat: is allocating a string and queuing up an autorelease on it... so you need to retain it somewhere.
I assumed you were doing this somewhere because you aren't getting an "EXC_BAD_ACCESS" - but rather, supposedly, a leak.
You shouldn't be leaking an autoreleased object unless you've retained it somewhere (hence the assumption).
Given you need to be retaining it somewhere, my above suggestions are valid - each retain needs a matching release.
I do agree that you should be using properties for these strings.
It's simple to convert them - and takes care of a lot of things for you.
In your Interface:
#property (nonatomic, copy) NSString * strLatitude;
In your Implementation:
#synthesize strLatitude;
To assign:
self.strLatitude = ...
(the "self." part is important)
And make sure you set that to nil in dealloc.
Related
I have a CLLocation that I set to the current location within the following function
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation{
currentLocation = newLocation;
}
When I try to access the current position in a later method the app crashes.
NSLog(#"current latitude is %f", currentLocation.coordinate.latitude);
NSString *longitude = [NSString stringWithFormat:#"%g", currentLocation.coordinate.longitude];
NSString *latitude = [NSString stringWithFormat:#"%g", currentLocation.coordinate.latitude];
The current position is set in the first method. I can print it out, what is weird is that I have this currentLocation defined as a pointer in the header.
The app crashes and there is no stacktrace. The debugger just sends me to the retValue of my app.
I tried retaining the pointer as well as alloc before setting it to the newLocation, but nothing seems to work.
What am I missing :D
I'm not so sure about your code but I can suggest this
I tried retaining the pointer as well as alloc before setting it to the newLocation, but nothing seems to work.
You need to retain newLocation pointer not the currentLocation before setting.
currentLocation = [newLocation retain];
or
self.currentLocation = newLocation;
Because your assignment currentLocation = newLocation; does not retain the pointer and newLocation is autorelease.
The app crashes and there is no
stacktrace. The debugger just sends me
to the retValue of my app.
Are you using Xcode 4? A lot of people are having trouble with the new interface. At the bottom of the stack trace window there's a slider, if it's set to be "coarse" it'll only show the app's main() block.
As indicated in the comments above, I reckon you should be saying self.currentLocation instead of currentLocation. The difference is that when you just say currentLocation, you are only assigning a pointer. To get all the "magic" functionality that you define in the header file (retain, et al), you need to use the self.currentLocation notation, OR, [self setCurrentLocation:newLocation];. Functionally those are the same, it's a matter of style.
Removed release statements. Some of them seemed to be okay, but that was probably just because other things were exploding first.
- (void)handleNowPlayingItemChanged:(id)notification {
MPMediaItem *item = self.musicPlayer.nowPlayingItem;
NSString *title = [item valueForProperty:MPMediaItemPropertyTitle];
NSNumber *duration = [item
valueForProperty:MPMediaItemPropertyPlaybackDuration];
float totalTime = [duration floatValue];
progressSlider.maximumValue = totalTime;
CGSize artworkImageViewSize = self.albumCover.bounds.size;
MPMediaItemArtwork *artwork = [item valueForProperty:
MPMediaItemPropertyArtwork];
if (artwork) {
self.albumCover.image = [artwork imageWithSize:artworkImageViewSize];
} else {
self.albumCover.image = nil;
}
titleLabel.text = title;
/*OpenEars stuff*/
}
In another question I mention the SQLite errors concerning artwork.
** Deleted error and details concerning NSZombieEnabled alert of call to released objects. **
Well don't I feel stupid. It was all memory management.
I put effort into not leaking anything, even in a temporary solution, and yet I did this...
In the code you provide I do not see any calls to retain, alloc/init, or some variation of copy. That means that you should not have a any calls to release in that method and that will be the cause of your crash. Make sure you are not over releasing in other methods and remember the basics of memory management.
You're releasing title and artwork, but they're not yours. This will lead, soon or later, to a tentative to release an already deallocated object (from item's dealloc or somewhere else).
// [artwork release];
//[title release];
comment those since those are autoreleased object
I am just reading through the Practical Memory Management guide.
I am somewhat confused by this block of code:
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
It seems to me that string is going to have a reference count of 0. Is this true?
What stops string from being deallocated before we call NSLog(string)?
Is this somehow equivalent to this:
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
Edit: Similarly this code is given in the Practical Memory Management
guide:
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:#"%# %#", firstName, lastName];
return string;
}
When and how does the return value get freed? Who is the owner? Does the caller of fullName need to release the string returned by full name?
Strictly speaking,
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
Is not equivalent to
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
The convention is that a method should autorelease any object it returns. The only exception (AFAIK) is for constructors, which return an object with a +1 retain count. Since [NSString stringWithFormat:] returns an object. In first snippet, stringWithFormat: returns an already autoreleased object. the second snippet, you're retaining it once more and it'll be released twice (which has the same effect, but the second retain/autorelease pair is redundant).
Ok, now to answer your question. Essentially, every time UIKit calls your code, it creates an NSAutoreleasePool object. Every time you autorelease an object, its added to this pool. Finally, when your code returns back to UIKit, it calls the drain method on the pool (i.e [pool drain]) and that releases every object which has been added to the pool and deallocates the pool. Also, autorelease pools can be nested, so you can create your own pools and drain them if you're going to be creating a lot of autoreleased objects. It isn't as complicated as it sounds.
I'd highly recommend that you read the Autorelease Pools chapter in the Memory Management Guide (Which incidentally, comes right after the Practical Memory Management chapter).
First of all:
NSLog(string);
Don’t do this. (I just realized it comes right from the Apple docs. Weird.) The first argument to NSLog is the formatting string. If your string contains some percent escapes, bad things will happen. The correct, if slightly longer way is:
NSLog(#"%#", string);
Now to the point: Autoreleased objects do not have zero retain count. They have retain count 1+ and have a pending –1 operation on them that will happen “soon in the future”.
The precise meaning of “soon in the future” depends on the situation. If you’re on the main thread and there is no additional autorelease pool in place, autoreleased objects will be released on the next runloop iteration. This does not have to be the case if you have an additional release pool:
// Let’s pretend this is a long loop and you don’t want to wait
// for the autoreleased objects to be collected by the main pool.
for (…) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *foo = [NSString stringWith…];
[pool drain];
// Now foo is no longer valid.
}
As for returning autoreleased objects, that’s one of the main use cases for autoreleasing. You are returning an object that will perish “soon”, but if the caller is interested, he can retain and take over the ownership. (It’s like, if you pardon the image, passing a bomb with a burning safety fuse. If the caller is interested, he’ll put out the fuse by retaining.) And if the caller is not interested, like maybe he’s ignoring an output from a function or just uses the value to construct some other object, he does not do anything and the object will get out of memory:
- (id) createObject {
return [NSString stringWith…];
}
- (void) interestedCaller {
NSString *value = [[self createObject] retain];
}
- (void) notInterestedCaller {
[self createObject]; // maybe just interested in side effects
NSString *differentString = [NSString stringWithString:[self createObject]];
}
This is really convenient and makes the manual memory management quite pleasant. You might be interested in run loops and the Objective-C tutorial by Scott Stevenson.
I have two leaks shown by the instruments tool. I have looked around on google but I haven't seen exactly my problem on there.
Problem #1:
self.wallText = [[text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
I have tried various configurations of the above line but all leak. I need to do both those trimming operations. 'text' is declared with either #"" or stringWithFormat.
My other issue is with the following line:
NSString * value = [elements objectAtIndex:i+1];
if ([value length] >= 2 && [[value substringToIndex:2] isEqualToString:#"S_"]){
value = [value substringFromIndex:2]; // LEAK HERE
}
I need to get all of the string except for the first 2 characters so I don't know how I could release it first or something... if that is indeed what I should be doing.
I could get away wtih leaks before with previous projects but this one is very memory intensive and I need all the memory I can get!
Any pointers would be greatly appreciated
Did you declare #property (retain) for wallText, did you do [wallText release] in dealloc method?
Double check above things and you will not have leaks any more
For Updated Part:
It is really strange that you have a memory leak there. Because at first, your value points to an autoreleased object then it points to another autoreleased object which I think is fine.
have u use alloc for value. value = [value substringFromIndex:2]; .here now value is referencing to new autorelease string. so u can not release previous object.
If I have a method
- (void) myMethod:(NSString *)string {
[Object anothermethodWithString:string];
}
and I call
[Object myMethod:#"this is a string with no alloc statement"]
Do I need to do something like
- (void) myMethod:(NSString *)string {
NSString *string2 = [[NSString alloc] initWithFormat:#"%#", string];
[Object anothermethodWithString:string2];
[string2 release];
}
instead of the way I had myMethod before? I have misbehaving code that seems to be caused by a string being auto-released while a second method within another method is being called (like in the example). The second way I have myMethod fixed all of my problems.
So is a "non-alloc" string an auto-released string? I asked this question as a follow up to another question (which was completely unrelated and is why I am creating this post), and a few sources said that I don't need to reallocate the string. I am confused, because the behavior of my code tells me otherwise.
Dave's got it right. You only need to worry about calling release on objects that you new, alloc, retain, or copy.
The above rule works very well, but if you're curious and want to get into a lot of detail, I suggest reading the Memory management Programming Guide from Apple's docs. It's free and goes from basic concepts into a lot of details.
If you use : NSString *str = #"". It is kind of a constant, you don't need to do any memory management.
If you call from a method : NSString *str = [NSString stringWithFormat:#""], the str is already autoreleased.
If you manually alloc, init. You need to call release, or autorelease yourself.
The general memory convention is : if you do something with new, alloc, retain, or copy, you need to release it yourself, any other cases, the object is autoreleased, don't release it