Objc memory crash with autorelase - objective-c

I have been hunting all over my code and can't find the source of this crash:
I am trying to decode an object with an NSKeyedUnarchiver and it crashes on it every time and says:
*** __NSAutoreleaseFreedObject(): release of previously deallocated object (0x1008ad200) ignored
*** __NSAutoreleaseFreedObject(): release of previously deallocated object (0x1008ab200) ignored
*** __NSAutoreleaseFreedObject(): release of previously deallocated object (0x1008a8c00) ignored
Ha my bad the reason why initWithCoder was not getting called was it was having issues with the [super initWithCoder:]; This is still driving me crazy. I looked and the pointers and the NSData objects are what are going wrong:
vertices = malloc(size_point3D * vertexCount);
textureCoords = malloc(size_point2D * textureCount);
normals = malloc(size_point3D * normalCount);
faces = malloc(sizeof(GLuint) * faceCount);
NSData *vertexData = [[NSData alloc] initWithData:[coder decodeObjectForKey:#"vertices"]];
NSData *textureData = [[NSData alloc] initWithData:[coder decodeObjectForKey:#"textureCoords"]];
NSData *normalData = [[NSData alloc] initWithData:[coder decodeObjectForKey:#"normals"]];
NSData *faceData = [[NSData alloc] initWithData:[coder decodeObjectForKey:#"faces"]];
memcpy(vertices, [vertexData bytes], sizeof(point3D) * vertexCount);
memcpy(textureCoords, [textureData bytes], sizeof(point2D) * textureCount);
memcpy(normals, [normalData bytes], sizeof(point3D) * normalCount);
memcpy(faces, [faceData bytes], sizeof(GLuint) * faceCount);
[vertexData release];
[textureData release];
[normalData release];
[faceData release];
I have tried retaining everything in this part (even the string) but it does not help.

This was a hard one to solve partly because debugging memory behaves inconsistently.
I have 2 classes JGStaticModel and JGModel. For some reason, the unarchiver would pick one of those at random so sometimes initWithCoder was sent to JGModel and not JGStaticModel. This led me to think it was not being called. Also since their structure is slightly different it had issues and crashed. The reason why I got the autorelease problem was I patched some memory problems in JGStaticModel but not JGModel so it would crash on the memory because I had not fixed it there.
Thanks for all the help!

Try turning on NSZombieEnabled, this should help you track down the problem.

If neither tools (Run -> Run with Performance tools) and NSZombiesEnabled helps, you can override - (id)retain and - (void)release methods of the class that caused the exception. Call super implementation and log retain/release. You can break in this methods to see the call stack. This way isn't beautiful, however, it helped me few time to figure out where was an extra release/autorelease call

This problem is very easy to solve with the solution given here.
The relevant part is:
If an environment variable named "NSAutoreleaseHaltOnFreedObject" is set with string value "YES", the function will automatically break in the debugger

Related

Crash when trying to present UIActivityViewController

I see a crash in Crashlytics than happens to my users sometimes. The crash happens when presenting UIActivityViewController in the last line of the following code:
NSData* snapShot = ... ;
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:[NSArray arrayWithObjects:activityTextsProvider, snapShot ,nil] applicationActivities:[NSArray arrayWithObjects:customActivityA, customActivityB, customActivityC, nullptr]];
activityViewController.excludedActivityTypes = [NSArray arrayWithObjects:UIActivityTypePrint, UIActivityTypeAssignToContact, UIActivityTypeMail, UIActivityTypeCopyToPasteboard, nil];
activityViewController.popoverPresentationController.sourceView = self.myButton;
activityViewController.popoverPresentationController.sourceRect = self.myButton.bounds;
activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError)
{
...
};
[self presentViewController:activityViewController animated:YES completion:nil];
I perform this in the main thread and unable to reproduce this crash locally. What could be the reason of this crash?
Edit: I changed nullptr to nil and the issue still happened. I managed to reproduce the issue: the crash happens only if before opening the activity controller i showed a UIMenuController. When creating UIActivityViewController it is not nil, but when presenting the controller i see the crash in the presentViewController line and the activity controller there is shown as nil
József addressed the use of nullptr in comments, and Fogh is spot-on that the actual crash log is important (please edit your question and post the full crash log), but I'd like to point out something else.
You're assuming your call to initialize activityViewController is succeeding. You should code defensively (by assuming everything that can fail probably will fail and testing for this at runtime). Wrap the rest of the configuration and presentation inside an if (activityViewController != nil) {} condition (you should probably have an else with proper error handling/reporting too) so you're properly detecting an all-out initialization failure for multiple reasons (like a misplaced nib, missing resource, etc.).
In your case, I think it's likely the initialization is failing because your class is doing something with a faulty array, as József's nullptr catch suggests. Perhaps you're using one or more pre-C++11 c libraries / compiling with a non-C11/gnu11 "C Language Dialect" build setting and nullptr is not equivalent to nil, leading to strange results in a supposed-to-be-nil-terminated array?
Note: If that turns out to be the case, I'll happily take an upvote but would rather József post his comment as an answer so you can give him proper credit. (Feel free to edit this request out of my answer if/when that happens.)

OS X ARC memory increase in repeated image loading

I have come across an issue when loading different NSImages repeatedly in an application written using Automatic Reference Counting. It seems as though ARC is not releasing the image objects correctly, and instead the memory usage increases as the list is iterated until the iteration is complete, at which point the memory is freed.
I am seeing up to 2GB of memory being used through the process in some cases. There's a good discussion on SO on a very similar issue which ends up putting the process in an NSAutoReleasePool and releasing the image and draining the pool. This works for me as well if I don't use ARC, but it is not possible to make calls to these objects / methods in ARC.
Is there any way to make this work in ARC as well? It seems as though ARC should be figuring this out all by itself - which makes me think that the fact that these objects are not getting released must be a bug is OS X. (I'm running Lion with XCode 4.2.1).
The kind of code which is causing the issue looks like this:
+(BOOL)checkImage:(NSURL *)imageURL
{
NSImage *img = [[NSImage alloc] initWithContentsOfURL:imageURL];
if (!img)
return NO;
// Do some processing
return YES;
}
This method is called repeatedly in a loop (for example, 300 times). Profiling the app, the memory usage continues to increase with 7.5MB alloced for each image. If ARC is not used, the following can be done (as suggested in this topic):
+(BOOL)checkImage:(NSURL *)imageURL
{
NSAutoReleasePool *apool = [[NSAutoReleasePool alloc] init];
NSImage *img = [[NSImage alloc] initWithContentsOfURL:imageURL];
if (!img)
return NO;
// Do some processing
[img release];
[apool drain];
return YES;
}
Does anyone know how to force ARC to do the memory cleaning? For the time being, I have put the function in a file which is compiled with -fno-objc-arc passed in as a compiler flag. This works OK, but it would be nice to have ARC do it for me.
use #autoreleasepool, like so:
+(BOOL)checkImage:(NSURL *)imageURL
{
#autoreleasepool { // << push a new pool on the autotrelease pool stack
NSImage *img = [[NSImage alloc] initWithContentsOfURL:imageURL];
if (!img) {
return NO;
}
// Do some processing
} // << pushed pool popped at scope exit
return YES;
}

EXC_BAD_ACCESS in objective c

Could someone help me with code below? Randomly get EXC_BAD_ACCESS in this loop. I guess there something wrong with [NSString stringWithFormat:....], but don't understand why and don't know how to fix. Thank you very much.
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
CGRect tileFrame=CGRectMake(i*tileSize, j*tileSize, tileSize, tileSize );
UILabel * t=[[UILabel alloc]initWithFrame:tileFrame];
t.text=[NSString stringWithFormat:#"%i",j*row+i];
///If there is a crashing ,it always stop at here, right after the [NSString stringWithFormat:.....]
t.backgroundColor=[UIColor clearColor];
//NSString * temps=[NSString stringWithFormat:#"%i",j*row+i ];
//t.text=temps;
[myView addSubview:t];
[t release];
}
}
BTW, I read some post online, I was told to do it in the way below can fix the problem. I'm not sure about this, why need to retain an autorelease object when this object is still in its scope. And more important shouldn't I release the retain object somewhere? Otherwise there will cause a memory leaking.
replace
t.text=[NSString stringWithFormat:#"%i",j*row+i];
with:
NSString * temps=[NSString stringWithFormat:#"%i",j*row+i ];
[temps retain];
t.text=temps;
i have tested it in my device and it is not crashing .
i have added 't' in self.view , i think there may be a problem with myView
This error is because you work with an object which was released previously. Try to setup these settings:
They are in Project >> Edit Scheme >> Arguments
Then place the console output here.

Can I use autorelease to fix this memory leak?

I have a memory leak in my iPhone app. I added Google AdMob to my app using sample code downloaded from Google. However, I was having a hard time getting it into testing mode so I added an extra variable as follows:
GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
I found the memory leak using Instruments. Instruments does not lead me to this line of code, it just dumps me in the main.m file. However, when I comment out the code relating to AdMob the leak goes away and I know enough to see that I haven't taken care of releasing this new variable. I just don't know exactly how I should set about releasing it. The variable r is not addressed in the header file so this is all the code that deals with it.
I tried adding:
- (void)dealloc {
[r release];
....
}
but that caused a build error saying "'r' undeclared". That's weird because it looks to me like I'm declaring r in the first quoted line above but I guess that's wrong. Any help would be much appreciated. I really have tried to educate myself about memory leaks but I still find them very confusing.
Just add [r release]; right below the code:
GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
[r release];
The variable r is declared only in that section of your code, so that's where it should be released. The point of releasing is to get rid of it as soon as you no longer need it, so the above should work perfectly for you.
If your r is locally declared (as it seems, judging from your snippet), then it cannot be accessed from outside its scope (here: the method it was declared in).
You either need to make it accessible within your class instance by declaring it an ivar.
Declaring it an ivar would look like this:
#interface YourClass : SuperClass {
GADRequest *request;
}
//...
#end
You then change your code to this:
request = [[GADRequest alloc] init];
request.testing = YES;
[bannerView_ loadRequest:request];
Also don't forget to release it in dealloc:
- (void)dealloc {
[request release];
//...
}
However this is not what you want in this situation (I've just included it to clarify why you get the warning about r not being declared).
You (most likely) won't need request any second time after your snippet has run, thus storing it in an ivar will only needlessly occupy RAM and add unwantd complexity to your class. Stuff you only need at the immediate time after its creation should be taken care of (released) accordingly, that is within the very same scope.
What you'll actually want to do is simply (auto)release it, properly taking care of it.
Keep in mind though that your loadRequest: will need to take care of retaining r for as long as it needs it. Apple's implementation does this, of course. But you might want to write a similar method on your own one day, so keep this in mind then.
GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
[r release]; //or: [r autorelease];
OP here. Thanks for all the detailed and thoughtful responses. This has definitely helped get a better handle on memory management. I did exactly as recommended, adding [r release]; right below the posted code. However, I still have a leak. I have isolated it to a single line of code. The following leaks:
GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
[bannerView_ loadRequest:r];
[r release];
The following does not leak:
GADRequest *r = [[GADRequest alloc] init];
r.testing = YES;
// [bannerView_ loadRequest:r];
[r release];
I figure I'm changing the retain count on bannerView with the loadRequest but I don't know how to fix it. I tried a [bannerView_ release] immediately after the [r release]; line (i.e. releasing locally) but that didn't work. I didn't expect it to because bannerView_ is declared elsewhere. I tried [bannerView_ release]; in the dealloc method but that didn't work. I also tried [bannerView_ autorelease]; locally. The wise heads at Google put [bannerView_ release]; in the ViewDidUnload method.
It's possible that Instruments is just messing with my head. The leak appears after about 10 seconds but the app performs well and the amount of memory leaked doesn't seem to be spirally upwards as the app continues to run. Is there such a thing as a benign memory leak?
Thanks again for your help,
Dessie.

NSDATA writeToFile crashes without a reason

I am downloading images from a url using NSDATA and saving them to local file system using
NSData *dataForStorage = [NSData dataWithData:UIImagePNGRepresentation(img)];
BOOL saveResult=[ dataForStorage writeToFile:jpegFilePath options:NSDataWritingAtomic error:&error];
NSLog(#"Write returned error: %#", [error localizedDescription]);
My app crashes randomly without even giving a message, though some files are saved (again randomly). When I run the app in Debug mode, I frequently see "EXC_BAD_ACCESS" but continuing execution succeeds in saving some of the files.
This code is executed in background from:
[self performSelectorInBackground:#selector(loadImageInBackground:) withObject:arr];
Please suggest.
One of the problems in your code is that your running code in a thread without an autorelease pool but are using functions that would require one. Put the following code into the loadImageInBackground method:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// existing code
[pool drain];
This is probably just one of several problems. For further assistance, we need to see the stack trace of the crash.
Just a wild guess : arr is an autoreleased object, so, sometimes it gets deallocated before your selector gets called. Try using [arr copy] and release it after saving it.
I was having the EXACT same problem, but it turned out that the problem was something else: my URL was getting release prematurely. In the end this is what I did and it worked:
I made this call:
[self performSelectorInBackground:#selector(downloadData:) withObject:nil];
And this is the method:
// URL - (NSString) URL for file
// filePath - (NSString) save location on device
-(void)download:(NSString *)URL
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:URL]];
[data writeToFile:filePath atomically:YES];
[pool release];
}
So I think that your download code is correct, but there is some other variable that is getting deallocated early (possibly your path).
Hope this helps! I know the other answers on this page worked for me.