NSString Memory Warning in objective c - objective-c

NSString* strSubject = [[NSString alloc] initWithData: temp encoding:
NSISO2022JPStringEncoding];
i got a memory message "Potential leak of an object allocated" on above line.
Is there any alternate way to write same.

You will get that sort of message unless you either release it or put it in the autorelease pool.
This can be done by:
NSString* str = [[NSString alloc] initWithData: blah blah blah ... ];
[str release];
to do it immediately. You can also use:
NSString* str = [[NSString alloc] initWithData: blah blah blah ... ];
[str autorelease];
to have it released at some point in the future.

You need to do [strSubject release] later, or [strSubject autorelease] either later or immediately. I'd use this:
NSString* strSubject = [[[NSString alloc] initWithData:temp encoding:NSISO2022JPStringEncoding] autorelease];
Sadly there isn't a NSString factory method stringWithData:, but that's equivalent.
In fact any [NSString stringWithBlah:xx] method is more or less equivalent to [[[NSString alloc] initWithBlah:xx] autorelease]

Related

memory menagement in ios

Can anybody explain me why does the case1 and case2 crashes while the others does not in case of non-ARC?
Case1:
NSString *rr = [[NSString alloc] initWithString:#"AB"];
[rr release];
[rr autorelease];
Case2:
NSString *rrr = [[NSString alloc] initWithString:#"AB"];
[rrr autorelease];
[rrr release];
Case3:
NSMutableString *rr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rr1 release];
[rr1 autorelease];
Case4:
NSMutableString *rrr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rrr1 autorelease];
[rrr1 release];
Case5:
NSArray *rr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rr3 release];
[rr3 autorelease];
Case6:
NSArray *rrr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rrr3 autorelease];
[rrr3 release];
Case7:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 release];
[rr2 autorelease];
Case8:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 autorelease];
[rr2 release];
All are are incorrect because eventually all will be released twice, but some may coincidentally not crash.
The alloc allocates the object with a retain count of 1. release decreases the retain count 1. autorelease eventually decreases the retain count 1. That means that all are over released.
But as #Chuck mentions some instances are constants, are created at compile time and never released so release and autorelease can be called to many tines with no crash.
String constants are one instance of this this where over-releasing will not cause a crash:
NSString *s = #"aa";
Even over-releasing this is OK because the compiler is smart enough:
NSString *s = [NSString stringWithString:#"aa"];
But you will get a warning from the current LLVM compiler that using stringWithString with a literal is redundant.

Force release an autorelease object

Can I force an Autorelase object by calling a release without autorelease pool like that:
NSString *myString = [[[NSString alloc] init] autorelease];
[myString release];
Normally it's like that:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] init] autorelease];
[pool release];
The first sample will crash, since the string will get over-released. If you want to have control over the lifetime of your autoreleased objects, the correct approach is what your second sample does – create a local autorelease pool that you can drain when you want.
Your code will crash because global auto release pool will try to release the object later. Results in malloc double free error
You can do this:
NSString *myString = [[[NSString alloc] init] autorelease];
Or this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] init] autorelease];
[pool release];
But not this:
NSString *myString = [[[NSString alloc] init] autorelease];
[myString release];

Is [NSMutableString string] same as [[NSMutableString string] autorelease]?

I noticed a piece of code somewhere it does
NSMutableString *myString = [[NSMutableString string] autorelease];
Is it overkill? Shouldn't it be the same as [NSMutableString string]?
NSMutableString *myString = [[NSMutableString string] autorelease];
will lead to a crash if they aren't calling retain on it elsewhere.
[NSMutableString string]
is the same as
[[[NSMutableString alloc] init] autorelease]
Doesn't look right to me. Are you sure that the example you saw is actually doing this?
[NSMutableString string] is equivalent to
[[[NSMutableString alloc] init] autorelease]
So with the example you provided, you would get
[[[[NSMutableString alloc] init] autorelease] autorelease]
which would result in an over release and an exc_bad_access error.

NSDictionary selector error NSString with spaces

-(void)messageSend:(NSString *)message;
{
NSLog(#"messageSend");
urlString = [[NSString alloc] initWithFormat:#"http://someaddress/message/send?from=%#&msg=%#&latitude=0&longitude=0",appDelegate.userName,message];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithDictionary:[self request:urlString]];
NSLog(#"Dictionary response");
if ([dictionary count] > 0)
{
if ([[dictionary objectForKey:#"send"] isEqualToString:#"OK"] )
{
NSLog(#"envio de mensagem de %# Ok: %#",appDelegate.userName,message);
}
}
[urlString release];
[dictionary release];
}
Gives an error of -[__NSArrayM getObjects:andKeys:]: unrecognized selector sent to instance. After some testing with NSLogs, the line
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithDictionary:[self request:urlString]];
is the culprit, witch is calling this method:
-(NSDictionary *)request:(NSString *)requestString
{
url =[[NSURL alloc] initWithString:requestString];
request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
error = [[NSError alloc] init];
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[responseData retain];
NSString *tempString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSMutableDictionary *tempDict= [[[NSMutableDictionary alloc] init] autorelease];
if (request)
{
Parser *parser = [[Parser alloc] init];
tempDict = [parser readXMLString:tempString];
for (id key in tempDict)
{
NSLog(#"%# is %#",key,[tempDict objectForKey:key]);
}
}
[url release];
[error release];
[responseData release];
[tempString release];
return tempDict;
}
And it happens when the string of the message has spaces.
But it was not happening before.
I see a few peculiarities:
error = [[NSError alloc] init];
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
Usually, you simply do:
NSError *error = nil;
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
The error variable will be filled with the address of an autoreleased error object if there is an error, otherwise it should remain nil. Do not allocate one yourself, since you could be releasing the wrong one (the one returned by the sendSynchronousRequest:etc. method). This could cause an over-release at the end of your method.
NSMutableDictionary *tempDict= [[[NSMutableDictionary alloc] init] autorelease];
if (request)
{
Parser *parser = [[Parser alloc] init];
tempDict = [parser readXMLString:tempString];
In the if-block, you are overwriting the pointer to the tempDict you just created. That is a memory leak (but not the cause of your problem). Update: the one you created is autoreleased. No leak.
You also don't release the Parser used in the if-block (and local to it).
You never check the value of error to see if actually an error occurred. As I said, you should set error to nil before the invocation of sendSynchronousRequest:etc. and then check if it is still nil, and if not, react accordingly:
if (error)
{
// error handling
}
What is the return type of [parser readXMLString: tempString];? Could it be an array and not a dictionary? E.g. an array of dictionaries?
Add an
NSLog(#"%#", tempDict);
in request:, before you return the tempDict. What does it show?
The getObjects:AndKeys: is probably called in -[NSMutableDictionary initWithDictionary:]. Apparently the real type of the dictionary returned by request: is not a dictionary, it is an array. See what I wrote above.
The culprit is the line tempDict = [parser readXMLString:tempString]. In fact, this means your previous creation of a [[[NSMutableDictionary alloc] init] autorelease] is pointless, as it will just be overwritten by the return value of [parser readXMLString:tempString]. In any case, it appears the -readXMLString: method is returning an NSArray instead of an NSDictionary.

Objective-c when to release objects

-(IBAction)registerUpdate:(id)sender {
HTTPRequest* request = [[HTTPRequest alloc] initWithUrl:#"http://www.yahoo.com" delegate:self];
[request doRequest];
}
The HTTPRequest makes an asynchronous request and calls the onHTTPResponse method in the current class.
My question is do I have to release request? My guess is that I'm supposed to make it an instance variable?
[NSString stringWithFormat:#"Data received: %#", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]];
How would I release that string object, or should I assign it to a variable?
You release it with autorelease
[NSString stringWithFormat:#"Data received: %#", [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]]