I want to use the auto-release in my apps. I want to implement this methods
- (void)selectorConnect: (NSArray *)args
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//some code
[pool release];
}
Getting crash at [pool release] line. Any solution for that .
When you empty an autorelease pool, it calls autorelease on all objects inside it.
If you're getting a crash with the [pool release] line then you've added an object to the autorelease pool and have released it yourself.
Run the static analyser and see what warnings it gives you.
And if you still don't know, enable NSZombies and see what object is being released twice.
Finally, if that still doesn't help, add your code to the question and we can all take a look :)
Related
Today i faced a little problem, i wanted to know the reason of leak. Here is the code
[[NSURLConnection alloc] initWithRequest:request delegate:self];
This works fine no problem.
Now i was just wondering what happens to this allocated memory/object since no one is releasing it. So according to instinct i put autorelease while allocating like this:
[[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
This threw me an error and crash "[NSURLConnectionInternalConnection _withConnectionDisconnectFromConnection]: message sent to deallocated instance"
Just wanted to know the concept and reason behind.
EDIT: I am not using ARC.
Thanks.
I think you can not use autorelease here for better memory management please release connection object in connection delegate method
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
[connection release];
}
So when your connection get finished It will release the connection object or you can release it ni viewDidUnload also
[NSURLConnectionInternalConnection _withConnectionDisconnectFromConnection]
this was called after the Autorelease Pool released your NSURLConnection connection object.
Best way should be, have a reference for the variable and release it, once you are done fetching the data. (May be in the viewDidUnload: ?)
You can use this method for better memory management
NSURLConnection *connection=[NSURLConnection connectionWithRequest:urlRequest delegate:self];
Above connectionWithRequest method is class method and manage memory itself you don't need to release it.
As far as I know after allocating the connection object objc runtime adds the object to autoreleasepool then other delegate method sent to deallocated instances.
Why does methods that run in the background using performSelectorInBackground create lot of memory leaks?
Thanks.
Create an NSAutoReleasePool for the background thread.
Add this at the start of your called method
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
and at the end:
[pool release];
Check Apple's documentation about NSAutoReleasePools.
Have only one question "How to right dealloc object when app goes to background ?". I'm working on some app, everything works great and fine. When i put app to background and then start it again it's crashes. Not immediately(app stars right where i closed it) , but when i choose some of cells or just scroll tableview for example. So i'm pretty sure that app calls already released data.
here is example of dealloc
- (void)dealloc {
[anObject release];
[array release];
[locationManager release];
[currentLatitude release];
[currentLongitude release];
[filteredListContent release];
[super dealloc];
}
Any advises?
Unless you specifically deallocate things in your app delegate's applicationDidEnterBackground method, nothing should be deallocated for you automatically.
I have never experienced the problem you're having. Are you certain the same thing doesn't happen after a while even if you never put it in the background?
Here's a good explanation of how all of the backgrounding stuff fits together:
Understanding iOS 4 Backgrounding and Delegate Messaging
I review and re-write my own code. The problem was as i expected in deallocation of memory. I used autorelease where i shouldn't. It still weird cause app did crash when i open it again.
Thanks everyone, not you guys who gift to me 2 negs, you are jerks. Don't be offended,but instead of give some advise you just give ungrounded negs.
Never release any object like this. Use
- (void)dealloc {
if(anObject){
[anObject release];
anObject = nil;
}
if(array){
[array release];
array = nil;
}
//same approach for all.
[super dealloc];
}
I have a UIViewController and in that controller, i am fetching an image from a URL source. The image is fetched in a separate thread after which the user-interface is updated on the main thread. This controller is displayed as a page in a UIScrollView parent which is implemented to release controllers that are not in view anymore.
When the thread finishes fetching content before the UIViewController is released, everything works fine - but when the user scrolls to another page before the thread finishes, the controller is released and the only handle to the controller is owned by the thread making releaseCount of the controller equals to 1. Now, as soon as the thread drains NSAutoreleasePool, the controller gets releases because the releaseCount becomes 0. At this point, my application crashes and i get the following error message:
bool _WebTryThreadLock(bool), 0x4d99c60: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
The backtrace reveals that the application crashed on the call to [super dealloc] and it makes total sense because the dealloc function must have been triggered by the thread when the pool was drained. My question is, how i can overcome this error and release the controller without leaking memory?
One solution that i tried was to call [self retain] before the pool is drained so that retainCount doesn't fall to zero and then using the following code to release controller in the main thread:
[self performSelectorOnMainThread:#selector(autorelease)
withObject:nil waitUntilDone:NO];
Unfortunately, this did not work out. Below is the function that is executed on a thread:
- (void)thread_fetchContent {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *imgURL = [NSURL URLWithString:#"http://www.domain.com/image.png"];
// UIImage *imgHotspot is declared as private - The image is retained
// here and released as soon as it is assigned to UIImageView
imgHotspot = [[[UIImage alloc] initWithData:
[NSData dataWithContentsOfURL: imgURL]] retain];
if ([self retainCount] == 1) {
[self retain]; // increment retain count ~ workaround
[pool drain]; // drain pool
// this doesn't work - i get the same error
[self performSelectorOnMainThread:#selector(autorelease)
withObject:nil waitUntilDone:NO];
}
else {
// show fetched image on the main thread - this works fine!
[self performSelectorOnMainThread:#selector(showImage)
withObject:nil waitUntilDone:NO];
[pool drain];
}
}
Please help! Thank you in advance.
Yeah it can be really daunting to try and keep threaded stuff in sync.
The use case you describe sounds perfect for an NSOperation.
By using this approach you can have an NSOperationQueue as an ivar in the controller and release this in your controllers dealloc method.
The benefits are many, when the controllers view is visible in the scrollView it (viewWillAppear or loadView) starts retrieving the image using an NSOperation added to an NSOperationQueue, if the user then scrolls away before the operation is done and the NSOperationQueue is released, it will take care of sending a cancel message to all operations and in general close everything down in an orderly fashion.
If this is a central component in your app, which I guess it is since you put thought into releasing things that are "of screen", I would recommend having your controller display a "dummy image" in the loadVIew method and then start a fetch operation in the viewDidLoad. You could subclass NSOperation so that you just send it the URL and let it do its thing.
I did something similar some weeks ago where I had to continuously start threaded operations, but with a large chance the the user would do something that caused these to get canceled. That functionality is "build" into the NSOperation.
NSOperation question
Maybe someone can help me with this strange thing:
If a user clicks on a button, a new UITableView is pushed to the navigation controller. This new view is doing some database querying which takes some time. Therefore I wanted to do the loading in background.
What works WITHOUT leaking memory (but freezes the screen until everything is done):
WorkController *tmp=[[WorkController alloc] initWithStyle:UITableViewStyleGrouped];
self.workController=tmp;
[tmp release];
[self.workController loadList]; // Does the DB Query
[self.workController pushViewController:self.workController animated:YES];
Now I tried to do this:
// Show Wait indicator
....
WorkController *tmp=[[WorkController alloc] initWithStyle:UITableViewStyleGrouped];
self.workController=tmp;
[tmp release];
[self performSelectorInBackground:#selector(getController) withObject:nil];
}
-(void) getController {
[self.workController loadList]; // Does the DB Query
[self.navigationController pushViewController:self.workController animated:YES];
}
This also works but is leaking memory and I don't know why !
Can you help ?
By the way - is it possible for an App to get into AppStore with a small memory leak ? Or will this be checked first of all ?
Thanks in advance !
No, small memory leaks will not (most likely) you application to be rejected from appstore.
In your example as you run your method in separate thread you should create and dispose NSAutoreleasePool object for that thread to handle autoreleased objects. Following changes to getController method should do the trick:
-(void) getController {
NSAutoreleasedPool *pool = [[NSAutoreleasedPool alloc] init];
[self.workController loadList]; // Does the DB Query
[self.navigationController pushViewController:self.workController animated:YES];
[pool release];
}
For more details see Autorelease Pools section in memory management guide. Relevant quote from there:
If you spawn a secondary thread, you
must create your own autorelease pool
as soon as the thread begins
executing; otherwise, you will leak
objects. (See “Autorelease Pools and
Threads” for details.)
Btw, you're calling pushViewController: from a background thread. This is bad.
You should only do things to the UI - like pushing view controllers and changing UI items - from the main thread. If you don't, things break.
See the Cocoa Fundamentals Guide section titled "Are the Cocoa Frameworks Thread Safe?": it says "All UIKit objects should be used on the main thread only."