Hi all
I get memory leaks on the leaks instrument whenever I trigger this method. Do you think anything is wrong with this??
static NSString* readStringOrDie(InputData *input, size_t length, NSStringEncoding encoding)
{
NSString *str = [[NSString alloc] initWithBytes: readOrDie(input,length)
length: length
encoding: encoding]; // HERE THE LEAK COMES !!
if (!str)
[NSException raise: BERParserException format: #"Unparseable string"];
return [str autorelease];
}
That code is fine. Most likely the actor that receives str retains it and subsequently fails to release it. Instruments knows where memory that has leaked was allocated but doesn't know where it should have been released, so it can provide some slightly unhelpful clues.
Because of using NSException for recoverable error.
Related
What I did is
int main(int argc, char *argv[]){
NSString *str = [[NSString alloc] init];
str = #"a a a a a a a a a ";
[str release];
NSLog(#"string is %#",str);
return 0;
}
I think string will be nil because we release it before printing it. However, it is not. Therefore, my consumption is wrong.
Can anybody advice me and correct me. Any comments are welcomed. Thanks
You are leaking memory there, first you allocate a new, empty, NSString object and then you assign a static string literal to the pointer, effectively leaking the memory you previously allocated. Then you release an object that you don't own as pointed out by The Saad and then you should note that release doesn't set the pointer to nil but just releases the object which might or might not end in an de-allocation (which, assuming that it would dealloc the object, would also not set the pointer back to nil).
NSString *str = [[NSString alloc] init];
This declares a variable that is a pointer to an instance of NSString, allocates memory for an instance of NSString, initialises that memory, then assigns a pointer to that memory to the variable you declared.
str = #"a a a a a a a a a ";
This creates an NSString constant and assigns a pointer to it to the variable that you declared. As you no longer have a reference to the original NSString object you created, you have leaked the memory you allocated for it.
[str release];
This declares that this code no longer wishes to be an owner of the memory allocated to str. As you created it with a string literal, this object will always exist in your program, and releasing it does nothing.
I think string will be nil because we release it before printing it.
Releasing an object does not ever set it to nil.
The str variable is a pointer to the string object and essentially contains a memory address. Sending a message like retain to the object does not change the value of the variable.
Just because the string is released will not cause the variable to lose its value. You must expicitly set the variable to nil for that to happen.
Note that with ARC under iOS 5 you can get weak references/pointers which will become nil when their underlying object is released. You do this by prepending a variable declaration with the __weak keyword (or use weak in a property declaration).
String constants are not to be released; they're neither explicitly to be released neither autoreleased; they're simply constants (by the way, they're deallocated at end of scope).
So, only -release them if you previously retained them
Here is the source corrected:
I'm afraid that there is much to learn before fully understanding what is going on. You should also look at understanding malloc (don't use it though), and how pointers work in C.
int main(int argc, char *argv[]){
NSString *str = [[NSString alloc] initWithString:#"a a a a a a a a a "];
[str release];
str = nil;
NSLog(#"string is %#",str);
return 0;
}
int main(int argc, char *argv[]){
NSString *str = #"a a a a a a a a a ";
// DONT Call this - the str [str release]; - no need to release this kind of string
NSLog(#"string is %#",str);
return 0;
}
I'm a newbie when it comes to objective C, and am currently experiencing a memory leak with the following code snippet. The memory leak occurs with the 'responseObj' allocation. Whenever I try to release it similar to responseData, I get a crash.
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString* responseStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSMutableArray* responseObj = [responseStr objectFromJSONString];
[delegate loadGameDetails:[responseObj objectForKey:#"result"]];
[responseStr release];
[responseData release]; responseData = nil;
}
I also tried to autorelease as below, but I also get a crash:
[delegate loadGameDetails:[[responseObj objectForKey:#"result"] autorelease]];
What's the proper way for me to release this block of memory?
The problem is not in your allocation. Your are sending objectForKey: to a NSMutableArray which is actually a NSDictionary/NSMutableDictionary method. Double check what type of object objectFromJSONString really returns.
Nothing in that code is leaking. You have a possible over-release of responseData but I can't tell since the declaration and setup of it is not in scope. If it is an ivar you would typically set it to nil via the accessor (which would release it there) than directly as you have done here.
If there is a leak it is in your loadGameDetails method. What makes you think you have a memory leak? Have you run this through instruments, or used the static analyser?
After trying to print retainCount of object I get 2147483647. Why do I get such a result? It should be 1, shouldn't?
NSString *myStr = [NSString new];
NSUInteger retCount = [myStr retainCount];
NSLog(#"refCount = %u", retCount);
2011-09-08 17:59:18.759 Test[51972:207] refCount = 2147483647
I use XCode Version 4.1. Tried compilers GCC 4.2 and LLVM GCC 4.2 - the same result.
Garbage Collection option was set to unsupported.
NSString is somewhat special when it comes to memory management. String literals (something like #"foo") are effectively singletons, every string with the same content is the same object because it can't be modified anyway. As [NSString new] always creates an empty string that cannot be modified, you'll always get the same instance which cannot be released (thus the high retainCount).
Try this snippet:
NSString *string1 = [NSString new];
NSString *string2 = [NSString new];
NSLog(#"Memory address of string1: %p", string1);
NSLog(#"Memory address of string2: %p", string2);
You'll see that both strings have the same memory address and are therefore the same object.
This doesn't directly answer your question, but retainCount is not really all that useful and should not be used for testing. See this SO post for details.
When to use -retainCount?
While NSString's are an odd case (there are others in the framework) you might also run across this in other clases - it's one of the ways of creating a singleton object.
A singleton only exists once in the app and it's pretty important that it never gets released! Therefore, it will overwrite some methods of NSObject including (but not limited to):
- (id)release {
// Ignore the release!
return self;
}
- (NSUInteger)retainCount {
// We are never going to be released
return UINT_MAX;
}
This object can never be released and tells the framework that it's a singleton by having a ludicrously high retain count.
Checkout this link for more information about singleton objects.
I've seen this a couple of times regarding NSStrings, the retainCount returns the maximum count instead of the actual one when you try to look at retainCounts of strings in this manner.
Try this;
NSString *myStr = [[NSString alloc] init];
NSUInteger retCount = [myStr retainCount];
NSLog(#"refCount = %u", retCount);
Edit: Restored NSUInteger
I get a leak on the code below, any idea why? I am not allocating anything so why does it leak? It leaks 32 bytes
NSString *username = #"";
NSString *myString = #"some text";
NSRange range = [myString rangeOfString:#"username="];
//instrument shows a leak on the line below
username = [myString substringToIndex:range.location + range.length];
//I never release username or myString
There shouldn't have any leaks, myString and userName is autoreleased already. Maybe it is not released yet but it will be released in some future time
It looks as though the String has been autoreleased - so should get released on the next pass through the event loop (#2 shows an autorelease).
I have a simple example of what I don't understand about memory management on the iPhone:
- (IBAction)AssignAndReleaseOne :(id)sender {
for (int i=0;i<10;i++) {
someString = [[NSString alloc] initWithString:#"String Assigned"];
}
[someString release];
}
- (IBAction)AssignAndReleaseTen :(id)sender {
for (int i=0;i<10;i++) {
someString = [[NSString alloc] initWithString:#"String Assigned"];
[someString release];
}
}
I would expect to get a memory leak in the first method because I alloc 10 times (or is it 11 :) with only one release, but Instruments doesn't report any errors?
Am I or is Instruments correct?
Thanks Chris.
You won't get a leak, surprisingly enough. See :
Memory issue of NSString
You should be getting the memory leak you expect.
Instruments' leak detection algorithm is expensive to run, so it is only executed after a specified amount of time (I think it's defaulted to 10 seconds). You may have to let the application run for a while before Instruments picks up the leak.