I am trying to clean up my code from memory leaks and I am having problems with the 'release' method.
Here is my code:
NSArray *dict = [[NSArray alloc] initWithContentsOfURL:url];
if (dict == nil) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Error"
message:#"Cannot retrieve content. Please try again later."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return;
}
self.schedule = dict;
[dict release];
[url release]; //I receive a runtime error here, "BAD ACCESS"
I don't understand why when I don't get the same problem with the line above [dict release];
Since you didn't post the code showing how URL was created, here's a general rule to follow:
If create the object with a initializer that starts with "init", then you should probably release it. If it's created another way (convenience method), then it's autoreleased. For example:
NSArray *a = [[NSArray alloc]initWithContentsOfURL:url]; // release this later
NSArray *a = [NSArray arrayWithContentsOfURL:url]; // this will be auto released
Basically you just need to look at whether the framework gave you an autoreleased object or not, because you can't release an autoreleased object or you'll (obviously) get a crash.
Take a look at the Memory Management Guide. It should be required reading.
You are responsible for calling release eat time, you call either alloc, copy, or retain.
In this case you called alloc on dict, but (presumably, although it is not shown where url comes from) not on url.
Objective-C allows you to send messages (e.g. 'release') to nil pointers without consequence.
If the pointer is non-nil and points to something bogus (i.e. an object that's been released), you'll get an EXC_BAD_ACCESS exception. Where does the url parameter come from and what is its retain count ([url retainCount]) before you call release?
Related
I'm having problem understanding memory management when creating a dictionary with mutable arrays. I'm using the ios6 SDK with deployment target 5.1.
In the implementation of the class "Group" the method "namesAndEmails" builds an array "emails" that contains the emails addresses for Person objects with an email. If the Person object does not have an email the Person name is added to another array "namesWithNoEmail". The arrays are returned in a dictionary.
#import "Group.h"
#implementation Group
-(NSDictionary*) namesAndEmails {
NSMutableArray *emails = [[NSMutableArray alloc] initWithCapacity:0] ;
NSMutableArray *namesWithNoEmail = [[NSMutableArray alloc] initWithCapacity:0];
NSString *email;
NSString *name;
for (Person *p in allPersons) {
email = p.email;
name = p.name;
if ([email length]==0) {
[namesWithNoEmail addObject:name];
} else {
[emails addObject:email];
}
}
NSArray *keys = [NSArray arrayWithObjects:#"emails",#"names", nil];
NSArray *objects = [NSArray arrayWithObjects:emails, namesWithNoEmail, nil];
//[emails release];
//[namesWithNoEmail release];
return [NSDictionary dictionaryWithObjects:objects forKeys:keys];
}
Somewhere else in the code I wish to send an email to a group of people so I call the emailGroup method which gets a dictionary out by calling "namesAndEmails" on the group.
-(void) emailGroup:(Group*) g {
NSDictionary *emailInfo = [g namesAndEmails];
guestsWithNoEmail = [emailInfo objectForKey:#"names"];
guestEmails = [emailInfo objectForKey:#"emails"];
int nGuestsWithNoEmail = [guestsWithNoEmail count];
if (nGuestsWithNoEmail > 0) {
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"No emails" message:#"" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[alert show];
}
// some more code here
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:subject];
[picker setMessageBody:#"" isHTML:NO];
[picker setToRecipients:guestEmails];
[[self delegate ] presentModalViewController:picker animated:YES];
[picker release];
}
As far as I understand [NSDictionary dictionaryWithObjects:objects forKeys:keys] in "namesAndEmails" returns an autoreleased dictionary. But why does my code crash if I release the "emails" and "namesWithNoEmail" arrays? I thought that the dictionary would have ownership of the array after they are added and therefore it would be safe to release the arrays in the method. I guess that's not correct, but why?
Is the a more clean way of doing this? Thank you for any advice!
My first suggestion would be to use the "Product->Analyze" feature. If you leaking or over releasing somewhere, it will probably give you the exact chain of events.
Secondly, I can't see the linking between your methods nameAndEmails and emailGroup:. Because I can't see the connection, I can't tell you if the autorelease is causing the problem.
Autoreleased objects get released when the the main run loop cycles. So it's very possible your NSDictionary is getting released. You could test this by doing anything from setting the memory location as a "watch" in the debugger to putting printing something in the console lines each time the runloop your in cycles (I made the assumption your in the main run loop, so correct me if that's not true).
Other things you can do to track the problem would be to use "Zombies" in instruments or NSZombieEnable=YES in your configuration
I am trying to generate an UIActionSheet from a NSDictionary.
codeCountryMap is NSDictionary variable defined in .h file. The code compiled correctly but crashes on run time. But the whole code works when the initialization is done in the handleEvents method
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *codes = [NSArray arrayWithObjects:#"91", #"01", #"002", nil];
NSArray *cName = [NSArray arrayWithObjects:#"ABC", #"QWE", #"XYZ", nil];
codeCountryMap = [NSDictionary dictionaryWithObjects:codes forKeys:cName];
}
-(IBAction) handleEvents:(id)sender
{
UIActionSheet *displayCodeCountryMap = [[UIActionSheet alloc] initWithTitle:#"Select Country" delegate:self cancelButtonTitle:nil
destructiveButtonTitle:nil otherButtonTitles:nil,nil];
for(id key in codeCountryMap) {
[displayCodeCountryMap addButtonWithTitle:(NSString *)key];
}
[displayCodeCountryMap addButtonWithTitle:#"Cancel"];
displayCodeCountryMap.cancelButtonIndex = [codeCountryMap count];
displayCodeCountryMap.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[displayCodeCountryMap showInView:self.view];
[displayCodeCountryMap release];
[country resignFirstResponder];
}
The app crashes when the handleEvents: method is called.
Any kind of help would be greatly appriciated.
Thanks in advance.
This more than likely is a memory management issue. It looks like you are setting the iVar codeCountryMap to an autoreleased object of NSDictionary and not retaining it(at least not in this code snippet). This means that when the 'handleEvents' method is called the NSDictionary item has been released from memory.
Try either retaining the NSDictionary item or, if codeCountryMap is defined as a retained property, then use the following code to set it.
self.codeContryMap = [NSDictionary dictionaryWithObjects:codes forKeys:cName];
This will use the synthesized methods to set the property and retain it.
No need for 2 nils terminators in the otherButtonTitles argument. If you had passed in strings then it would have to be nil terminated. Since you did not, one nil is enough.
UIActionSheet *displayCodeCountryMap = [[UIActionSheet alloc] initWithTitle:#"Select Country" delegate:self cancelButtonTitle:nil
destructiveButtonTitle:nil otherButtonTitles:nil];
I have upgraded my XCode to versio 3.2.3 to support iOS4 on my iphone project. using the static analyser I checked for memory management problems.
In one of my routines I get the following problem:
I generate a user alert after adding an event to the calendar to give him a status.
This runs fine, but the memory analyser doesn't like how I defined the alert.
I can't see the coding problem, do you? (I indicated the memory analyser hints with "<<<<")
- (IBAction) addToCalendar {
...
UIAlertView *tmpAlert = [UIAlertView alloc]; <<<<Method returns an Objective-C object with a+1 retain count (owning reference)
calData.startDate = iVar.zeitVon;
calData.endDate = iEvent.zeitBis;
calData.title = iVar.title;
calData.calendar = myEventStore.defaultCalendarForNewEvents;
if ([tmpEventStore saveEvent:tmpEvent span:EKSpanThisEvent error:&tmpSaveError]) {
// Show a save success dialog
[tmpAlert initWithTitle:#"Success" <<<<Object released
message:#"entry saved" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
} else {
// Show a save error dialog
[tmpAlert initWithTitle:#"Error"
message:#"entry not saved" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] ;
}
[tmpAlert show]; <<<<Reference counted object is used after its released
[tmpAlert release];
}
thanks
You should never decouple alloc and init. init often changes the object behind the scenes! Try
NSString* foo=[NSString alloc];
NSLog(#"%p %#", foo, [foo class]);
foo=[foo initWithString:#"bar"];
NSLog(#"%p %#", foo, [foo class]);
You'll see something like
2010-07-14 01:00:55.359 a.out[17862:903] 0x10010d080 NSPlaceholderString
2010-07-14 01:00:55.363 a.out[17862:903] 0x100001070 NSCFString
This shows that +[NSString alloc] doesn't really allocate anything; rather, what does the job is initWithString itself. I don't think UIAlertView does this, but you never know.
To recap: never decouple alloc and init. I think the static analyzer just assumes that everyone use [[... alloc] init], so that it got confused by your code. The analyzer should have warned you not to decouple alloc and init.
I am using the location manager to generate location data that I send in a URL to down load data. The first time I call the location manager, it correctly returns the current location and based on the current location I can fetch the data from the URL.
However, when I attempt to retrieve the current location a second time, I receive a EXC_BAD_EXCESS.
When I try debugging with NSZombieEnabled it shows me FirstViewController.recievedData as a zombie in the didReceiveResponse method. (see marked code below)
I dug further and I found that after releasing the initial connection an unknown connection is established and then it tries to access receivedData which is already released .
The header file info :`
#import <CoreLocation/CoreLocation.h>
define SECS_OLD_MAX 1
#interface FirstViewController : UIViewController<CLLocationManagerDelegate> {
UIActivityIndicatorView *spinner;
CLLocationManager *locationManager;
CLLocation *startingPoint;
UIButton *relocateMe;
NSMutableData *receivedData;
NSString *lat;
NSString *lon;
}
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *spinner;
#property (nonatomic, retain) CLLocationManager *locationManager;
#property (nonatomic, retain) CLLocation *startingPoint;
#property (nonatomic, retain) IBOutlet UIButton *relocateMe;
#property (nonatomic, retain) NSMutableData *receivedData;
#property (nonatomic, retain) NSString *lat;
#property (nonatomic, retain) NSString *lon;
`
The .m file code :
//starting the manger :
[spinner startAnimating];
**EDIT**************************ADDED IN THE AUTORELEASE POOL BY HIB********************************
self.locationManager = [[[CLLocationManager alloc] init]autorelease];
// Detecting the user device
NSString *currentDevice = [[UIDevice currentDevice] model];
// if its iPhone then locate the current lattitude and longitude
if([currentDevice isEqualToString:#"iPhone"] || [currentDevice isEqualToString:#"iPhone 3G"] || [currentDevice isEqualToString:#"iPhone 3G S"]){
DLog(#"I have identified the device as an iPhone");
if(locationManager.locationServicesEnabled == YES){
DLog(#"ok now the location manager gets the property");
locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Once configured, the location manager must be "started".
[locationManager startUpdatingLocation] ;
}else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:#"Please enable location servies"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
//if its iPod then fetch the city based restaurants
else if([currentDevice isEqualToString:#"iPod touch"] || [currentDevice isEqualToString:#"iPod touch 2G"]){
}
else if([currentDevice isEqualToString:#"iPhone Simulator"]){
//TechZen says: there appears to be some code missing here, not sure if its relevant
}
//didupdatetolocation method
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
// store the location as the "best effort"
DLog(#"Lat = %g Long = %g",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
NSDate *eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
DLog(#"NSTIME INTERVAL = %i",howRecent);
//Is the event recent and accurate enough ?
if (abs(howRecent) < SECS_OLD_MAX) {
self.lat = [NSString stringWithFormat:#"%g",newLocation.coordinate.latitude];
self.lon = [NSString stringWithFormat:#"%g",newLocation.coordinate.longitude];
[[NSUserDefaults standardUserDefaults] setObject:lat forKey:#"LATITUDE"];
[[NSUserDefaults standardUserDefaults] setObject:lon forKey:#"LONGITUDE"];
DLog(#"inside Lat = %g Long = %g",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
self.startingPoint = newLocation;
[locationManager stopUpdatingLocation];
**EDIT********************************REMOVED BY HIB******************************
self.locationManager = nil;
[locationManager release];
**EDIT********************************REMOVED BY HIB******************************
**ADDED BY HIB********************************************
locationManager.delegate = nil;
**ADDED BY HIB********************************************
#try {
//passing the parameter for more condition
self.lat = [NSString stringWithFormat:#"%g",startingPoint.coordinate.latitude];
self.lon = [NSString stringWithFormat:#"%g", startingPoint.coordinate.longitude];
NSString *string2 = [[NSString alloc] initWithFormat:#"%#/Service.asmx/someMethod?lat1=%g&lon1=%g&recordSize=0"
,[[NSUserDefaults standardUserDefaults] stringForKey:#"textEntry_key"],startingPoint.coordinate.latitude,startingPoint.coordinate.longitude];
NSURL *url = [[NSURL alloc] initWithString:string2];
[string2 release];
NSMutableURLRequest* request2=[NSMutableURLRequest requestWithURL:url];
[request2 setHTTPMethod:#"GET"];
[request2 setTimeoutInterval:25.0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request2 delegate:self];
if (theConnection) {
receivedData = [[NSMutableData data]retain];
} else {
// inform the user that the download could not be made
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Sorry !"
message:#"The server is not avaialable \n Please try againa later"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[spinner stopAnimating];
}
[url release];
}
#catch (NSException * e) {
}
#finally {
}
}
}
//and the delegate methods
#pragma mark -
#pragma mark connection methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// it can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is declared as a method instance elsewhere
**************************************the zombie is here *********************************
[receivedData setLength:0];
*****************************************************************************************
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[spinner stopAnimating];
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
// inform the user
DLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
// alert the user in the inter face.
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:#"Sorry !"
message:#"The server is not available.\n Please try again later."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a method instance elsewhere
DLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
[spinner stopAnimating];
// release the connection, and the data object
if(receivedData == nil)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:#"Sorry !"
message:#"The server is not available.\n Please try again later or select city."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
[spinner stopAnimating];
}
else
{
//just parse and use the data
}
[connection release];
[receivedData release];
}
Please help . I am stuck.
You have a systematic problem with not properly accessing your class properties. The properties will not be automatically retained and released unless you use the self.propertyName to force the call to the accessors. For example:
[locationManager stopUpdatingLocation]; <-- direct access
self.locationManager = nil; <-- access through generated accessor
[locationManager release]; <-- direct access again with release bypassing the automatic memory management
You should have:
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
//[locationManager release]; this line is now unneeded because the accessor handles it
You have the same problem with recievedData and startingPoint. In the vast majority of cases, if you use the synthesized accessors you only need to call release on retained properties in your dealloc. Use the accessors will clear up your zombie problem.
Without knowing where the EXC_BAD_ACCESS occurs I can't say definitively but since that error often occurs when messaging an non-existant object I can say that it is very likely that your bypassing of the property accessors and your releasing of them manually is probably causing the code to send to nilled property.
Fix the access and see if that resolves the problem.
Edit01:
TechZen the problem is removed 50 %.
my application runs nicely in the
debugging mode but when I pull out the
cable and starts again it crashes .
the problem is certainly with location
manager . but I am not clear about
retains and release of location
manager . can you help me
I'll take a stab at it. For your memory management:
Always access your
self.locationManager using the
self-dot-propertyName notation to
make sure you utilize the
retention/release mechanism of
generated accessors.
Never call release on any property
except in the dealloc method. If
you use the self-dot notation and
have the property set to retain, all
but the end of life release is
handled automatically for you. This
includes times when you nil the
property or set it to another object.
When in doubt, don't release. It's easier to fix a memory leak latter than it is to track down a bug caused by an object that disappears at random points in the code because its retain count is skewed. Trying to hard to prevent leaks when your learning the environment is a form of premature optimization that causes more trouble than it prevents.
I note that in your locationManager:didUpdateToLocation:fromLocation: method you don't actually query the locationManager passed to the method but instead query the class's self.locationManager property. This may or not be a problem but it is best to use the passed in manager to make sure you are in fact querying the manager instance that updated. I also don't think it necessary to destroy and recreate the location manager repeatedly. I think you can initialize it once and keep it around (check the docs on that.)
If cleaning up your property references and using the passed manager does not help, I suggest you post a new question with the cleaned up code. At that point you will legitimately have a new issue and besides we need to see the cleaned up code to spot the problem.
Edit02:
(Based on new code)
You don't need to autorelease your 'self.locationManager' property here:
self.locationManager = [[[CLLocationManager alloc] init]autorelease];
You only use autorelease when you create an object and in your class and then send it to another class. You never autorelease properties of class.
You need to stop trying to release your declared properties. You never release properties defined with retain except in the dealloc method. You are stepping on the properties generated accessors that maintain the retain count automatically.
Your are still not using the accessors consistently. This:
if(locationManager.locationServicesEnabled == YES){
DLog(#"ok now the location manager gets the property");
locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Once configured, the location manager must be "started".
[locationManager startUpdatingLocation] ;
should be:
if(self.locationManager.locationServicesEnabled == YES){
DLog(#"ok now the location manager gets the property");
self.locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Once configured, the location manager must be "started".
[self.locationManager startUpdatingLocation] ;
and this:
locationManager.delegate = nil;
should be:
self.locationManager.delegate = nil; //<-- why are you doing this anyway?
You need to track down all references to all your declared properties and affix self. to each one (expect inside a properties custom accessor which you don't seem to have use -- which is good in this case.)
I strongly suspect your problem is your unnecessary fiddling with the retention of the self.locationManager property. You maybe causing the location manager to disappear at random.
You are still not using the passed manager in locationManager:didUpdateToLocation:fromLocation: I suggest you do so or at least test that the passed manager is the same object as your self.locationManager. simply replace self.locationManager with manager.
One think you are certainly doing wrong: you need to allocate receivedData before you start the NSURLConnection. It will fork in the background right when you alloc/init it, so receivedData needs to be ready before, not after.
You are releasing recievedData at the end of a connection but are not setting your pointer to nil - it will still be pointing at where recievedData used to be.
Instead of
[recievedData release];
try
self.recievedData = nil;
Hope that helps,
Sam
I could not find the source of your problem but you have a leak in
self.locationManager = [[CLLocationManager alloc] init];
you should use
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
instead.
Edit: Download Charles Web Proxy, check what connections you are making, what responses you get, and maybe we'll have a better idea then.
Edit after Comments: The autogenerated accessor property defined to retain automatically retains the passed object, and releases it when you set the property to nil/or release. So it soes ITS job, but its YOUR job to keep track of memory management of the passed object. So, yes, the initial code above has a LEAK, and you should do your job and RELEASE/AUTORELEASE your ALLOCATED object, which in this case happens to be [[CLLocationManager alloc] init].
Edit :
I don't know how this comment can get -1. It's simple memory management. The answers on this thread all agree this is a correct post:
iPhone: Is this a leak or not
I am not sure what was the actual problem . but when I was comparing the apple LocateMe example I see locatiomManager.delegate = nil; It solves the problem completely .
I have follwowing peace of code in which I have specified the leaky line . As I am new to iPhone developement I can't understand what actually is wrong with that line . please have a look at that line and tell me .
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
//take away
//NSURL *url1 = [[NSURL alloc] initWithString:#"http://url/Service.asmx/takeAwayList"];
NSURL *url1 = [[NSURL alloc] initWithString:[NSString stringWithFormat:#"%#/Service.asmx/takeAwayList",serviceURL]];
NSMutableURLRequest* request1=[NSMutableURLRequest requestWithURL:url1];
[request1 setHTTPMethod:#"POST"];
[request1 setTimeoutInterval:10];
//*****the leaky line***********************///
NSData *data2=[[NSURLConnection sendSynchronousRequest:request1 returningResponse:nil error:nil] autorelease];
if(data2 == nil)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"The network is not available.\n Please check the Internet connection." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
NSXMLParser *xmlParser1 = [[NSXMLParser alloc] initWithData:data2];
//Initialize the delegate.
TakeAwayParser *takeAwayParser = [[TakeAwayParser alloc] initTakeAwayParser];
//Set delegate
[xmlParser1 setDelegate:takeAwayParser];
//Start parsing the XML file.
#try {
BOOL success = [xmlParser1 parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
}
#catch (NSException * e) {
NSLog(#"Exception in parsing %# %#",[e name], [e reason]);
}
[takeAwayParser release];
[xmlParser1 release];
}
//[request1 release];
// [response1 release];
//
[url1 release];
// [data2 release];
//new arrivals
//[data2 release];
[pool release];
I had issues with this as well in my Large project. After working with an Apple engineer on trying to locate the leaks, he finally asked the main Apple dev team behind NSURLConnection. They basically said that there is an internal cache that is not clearable at all in NSURLConnection and it was a known issue.
So I set out looking for alternatives. I found ASIHTTPConnection (link below) which works off of CFNetwork. It is designed to be a drop-in replacement for NSURLConnection, plus a bunch of other awesome goodies like downloading to disk instead of memory, download resuming, progress bar callbacks etc..
I have used it in all my projects and have never had any issues or complaints. An, in answer to your question, this is how I got rid of those memory leaks.
http://allseeing-i.com/ASIHTTPRequest/
This line isn't leaking, you shouldn't even being autoreleasing it.
Do yourself a favor and read the Memory Management Guide in Apple's developer docs, commented out releases in your code do not bode well.
EDIT: Hrm I take that back your code is completely fine except for that one line. Are you sure that it's leaking? It's returning an object with a retain count of 0, so you autoreleasing it should be causing trouble because it already has a retain count of 0.