NSMutableArray removeAllObjects crash - ios

Car class
--------------
price
color
crash code is:
NSMutableArray *list = [[NSMutableArray alloc] init];
Car *car = [[Car alloc] init];
car.price = 10;
car.color = 1;
[list addObject:car];
// some code
[list removeAllObjects]; // Crash here
why crash, how can i resolve it.
app exit with nothing output

I dont know what you have in the "someCode" section in your segment. You first comment out that code and check if the app crashes. If still it crashes then only consider what I have given below. I mean you make sure there is nothing wrong with your code before going for workarounds :)
just try this code, and see if it crashes now.I know it doesn't make sense, but it happened to me once too. Once when array count was zero removeAllObjects crashed for me. I doubt an SDK bug somewhere there :(
if([list count]){
[list removeAllObjects];
}

Most likely you are releasing one or more of the objects in the array one too many times. When the NSMutableArray tries to release that object, it crashes because the object has already been disposed of.

I just ran into this same thing. In the dealloc method of my object I had:
-(void) dealloc
{
[super dealloc];// <--- le' culprit!
[Image_ID release];
[Image_Number release];
[Image_UID release];
[Series_ID release];
[Series_UID release];
[Study_UID release];
// <--- it should be here...
}
I moved [super dealloc] below all the releases..and my [.... removeAllObjects] worked fine..

At a guess, I'd say you're releasing list somewhere, and so your call to removeAllObjects is being sent to a deallocated instance. Impossible to be sure without a stack trace and some more detail, though—is it an EXC_BAD_ACCESS error or what?

Set the array property as Retain in interface section. Once I did same it worked for me. just try once.

Related

Safely perform changes to NSMutableArray

What can cause an assignment or change to an NSMutableArray to crash?
I have a mutable array containing custom objects, and I consistently keep no more than the 3 latest objects in it, the rest are removed. I started calling
[myArray insertObject:newObject atIndex:0];
if (myArray.count > 3)
[myArray removeLastObject]; // Crash
But whenever I do this too fast, the last line causes an exception-less crash.
I know that you are not allowed to add or remove objects of an array while it is being enumerated, but I do not enumerate myArray anywhere unless calling count on it performs an implicit enumeration. I also tried doing this:
NSMutableArray *tmp = [myArray mutableCopy];
[tmp removeLastObject];
myArray = tmp; // Crash
But the same thing happens, it crashes on the last line. Again, this works perfectly fine when doing it slowly. The action itself is being called when a user taps a button, and when tapping it too fast, it crashes every time.
EDIT:
I should add that all of this is being run inside the cellForItemAtIndexPath method of a UICollectionView.
First, could you please post the crash message. It would be nice to know what error you are actually seeing.
I wonder what would happen if you switched to immutable arrays. Switch myArray to being an NSArray * and use the following.
myArray = [self updatedArray:myArray withObject:newObject];
Where -updatedArray:withObject: is
- (NSArray *)updatedArray:(NSArray *)array withObject:(id)object {
switch (array.count) {
case 0: return #[object];
case 1: return #[object, array[0]];
default: return #[object, array[0], array[1]];
}
}
Or better for testing
NSArray *temp = [self updatedArray:myArray withObject:newObject];
myArray = temp; // I assume the crash will be here!
If the code crashed at my comment, then deallocating myArray is causing the crash. My guess is that one of the items in the array is pointing to bad memory (a zombie or some such thing).
I can think of two possible reasons for the crash:
1) The array is being accessed/mutated from multiple threads
2) An object inside the array was over-released somewhere, causing it to be deallocated while still living inside the array.
Short answer: try profiling your app in Instruments, and select the "Zombies" instrument. When the crash happens, you just might get a zombie alert, in which case you can get a back-log of everything that led up to your memory getting stomped over.
I think the root cause is this variable is accessed from multiple threads at the same time.
You can use this when access the array
#synchronized(self) {
//Your accessed code here
}

EXC_BAD_ACCESS error in block of code made in App Delegate

I don't understand whats causing an EXC_BAD_ACCESS - KERN_INVALID_ADDRESS error in my app.
When my app starts up, my AppDelegate.m I make a call to a SKProductRequest to get all the available IAPs for an app. It works sometime but not others and I'm at a loss to figure out why. My code in the AppDelegate to do this looks like the following:
[[MyIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
for (SKProduct *prod in products) {
// set up pricing in the db
[Price setPriceOfProduct:prod.productIdentifier WithLocale:prod.priceLocale AndAmount:prod.price];
}
}
}];
The requestProducts... method is simply:
- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
_completionHandler = [completionHandler copy];
_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers];
_productsRequest.delegate = self;
[_productsRequest start];
}
Any help on this is much appreciated - if I've left out any key information then just let me know.
For dealing with BAD_ACCESS, you should have a look at my answer in this post :
iOS error Terminating app due to uncaught exception 'NSRangeException Range or index out of bounds'
See how to add the "malloc_error_break" breakpoint. This might help to find out which line is causing the bug.
In your case, I suspect that your MyIAPHelper instance, or _productsRequest has been deallocated.
To check this, you should override the "dealloc" method of MyIAPHelper like this :
-(void)dealloc{
NSLog(#"MyIAPHelper is deallocated");
}
And add a breakpoint on the NSLog to see if dealloc is called.
You should also check that your _productsRequest property is retained (i.e. declared like this : #property(nonatomic,retain) SKProductsRequest* productsRequest;
Try Block_copy() instead of copy on the handler.
_completionHandler = Block_copy(completionHandler);
This answer should help.
(and don't forget to call Block_release(...) when you're done with it.

iOS Memory Leak Advice

I'm pretty sure this is causing a leak and I would like some advice. Here's code based on what I'm doing:
NSMutableArray* straVideoTitles;
- (void) parseData{
//stuff
straVideoTitles = [self getVideoTitle:strData]; //strData contains unparsed data
//more stuff
}
- (NSMutableArray*) getVideoTitles:(NSString*)strData{
NSMutableArray *array;
array = [[NSMutableArray alloc] init];
//Parse data and populate array
return array;
}
Based on the fact that I'm allocating space for NSMutableArray and not releasing it, thats a leak right? How do I tackle this? Should I forgo returning a value and assign straVideoTitles inside getVideoTitles then release like:
- (void) getVideoTitles:(NSString*)strData{
NSMutableArray *array;
array = [[NSMutableArray alloc] init];
//Parse data and populate array
straVideoTitles = array;
[array release];
}
or am i going about this all wrong? Or is everything fine because I'm releasing straVideoTitles in dalloc?
You could change the
return array;
into
return [array autorelease];
Or you could use ARC and just don't care about it anymore.
Edit: The second approach is possible and does not include a memory leak but the code is less capsulated and therefore less reusable and future prove.
Change to
return [array autorelease];
It is good practice to return autorelease objects from methods. This is called a deferred release message.
You are relinquishing ownership while allowing the caller of the method to use the returned array before it is deallocated.
Your return statement should read:
return [array autorelease];
For more information on memory management take a look here:
Advanced Memory Management Programming Guide

Setting NSDictionary object as a property in child view either leaks when not released or gives EXC_BAD_ACCESS error when released

I have the following problem: In a certain view controller I have a NSDictionary, which itself is an entree in an NSArray object. This view controller has a child view which displays some of the key value pairs that are in this dictionary. Since I need only some key value pairs, I construct a new dictionary object from which I then remove the key value pair I do not want to have in it. To be able to access this dictionary in the child view, I though it would be possible to just set the dictionary via a property, which seems to work fine. To illustrate with some code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
// today is an instance of NSArray holding a number of NSDictionary objects
NSDictionary *completeData = [self.today objectAtIndex:row];
NSDictionary *data = [[NSDictionary alloc] initWithDictionary:completeData];
[data removeObjectForKey:#"name"];
SomeViewController *childController = [[SomeViewController alloc] init];
childController.data = data;
[self.navigationController pushViewController:childController animated:YES];
[childController release];
// This results in a EXC_BAD_ACCESS error when navigating back to the parent
// view and calling didSelectRowAtIndexPath a second time. When commenting this
// line out, the error dissapears, but now the object leaks
[data release];
}
The problem arises when, after returning to the parent view, I try to replace the NSArray object (today) by an updated version of itself by calling
- (void)refreshDataNotification:(NSNotification *)notification {
if (notification) {
self.today = [NSArray arrayWithArray:[[[MyAppDelegate getAppDelegate] todaySchedule]
objectForKey:#"data"]];
[self.tableView reloadData];
}
}
Note that as long as I do not release 'data' in didSelectRowAtIndexPath I get no error, but then the object leaks. When I do release it, I receive an EXC_BAD_ACCESS when refreshDataNotification is executed.
If someone has any clue as to what I might be doing wrong, then please do share with me.
Set the environment variable NSZombieEnabled to YES to get more helpful error messages about over releasing objects. (Set the environment variable by viewing details under 'Executables')
Also, it would be helpful to see how you've defined your properties. (e.g. what is the #property for data in SomeViewController?)
ps - I know you haven't pasted actual code, but data is a terrible instance name for an NSDictionary. dict is better - but something more descriptive would make your code easier to understand.

NSMutableDictionary memory leak - how do I fix it without crashing the App?

I must have misunderstood some of the memory management rules, because when I try to fix a memory leak, the App crashes. Let me show you some code:
calendarRequestLog is a property of type MutableDictionary in a singleton object, that exists as long as the App runs. Here's the declaration in the .h file:
#property (nonatomic, retain, readonly) NSMutableDictionary *calendarRequestLog;
I allocate it with (in init):
calendarRequestLog = [[NSMutableDictionary alloc] init];
I fill it with this (notice the retain, that creates the memory leak):
[calendarRequestLog setObject:[[NSMutableArray arrayWithObject:delegate] retain] forKey:date];
I sometimes access it with this:
NSMutableArray* delegates = [calendarRequestLog objectForKey:date];
if(delegates != nil) {
// add delegates
}
I empty it with this:
NSMutableArray* delegates = [calendarRequestLog objectForKey:date];
if(delegates != nil) {
for (id <ServerCallDelegate> delegate in delegates) { … }
// clear the request from the log
[calendarRequestLog removeObjectForKey:date];
}
Here's the code that crashes when I remove the retain above:
NSMutableArray* delegates = [calendarRequestLog objectForKey:date];
if(delegates != nil) {
if([delegates containsObject:delegate]) // crash
[delegates removeObject:delegate];
}
It crashes because delegates is deallocated but not nil. To be more precise, I get an EXC_BAD_ACCESS Exception.
All these methods may be called in different orders or multiple times.
I cannot figure out, why this happens. I thought, collections are supposed to retain their objects - as this array-object (delegates) is still in the collection, it should not be deallocated. Other code cannot be responsible, I showed you all occurrences of calendarRequestLog.
I appreciate all the help I can get!
#Edit
I think I got it.
I call the crashing method when the delegate gets deallocated, so that I do not call the delegate per accident later.
But: I retain the delegates in my calendarRequestLog, so it cannot get deallocated as long as this doesn't get called:
// clear the request from the log
[calendarRequestLog removeObjectForKey:date];
...which in turn, deallocates the delegate and calls the crashing method. As the calendarRequestLog has removed the delegates, but not yet the key, we crash.
Ok, I will solve this differently. Thanks for all the comments - thanks to you, I looked elsewhere!
Did you try retaining when fetching so nobody releases your object while you're using it?
NSMutableArray* delegates = [[calendarRequestLog objectForKey:date] retain];
if(delegates != nil) {
if([delegates containsObject:delegate]) // crash
[delegates removeObject:delegate];
}
[delegates release];
Common practice is the following, because you already retain in the .h file:
//create local instance, then copy that to the class wide var
NSMutableDictionary *_calendarRequestLog = [NSMutableDictionary alloc] init];
self.calendarRequestLog = _calendarRequestLog;
[_calendarRequestLog release];
Also, I don't really understand why you would retain here:
[calendarRequestLog setObject:[[NSMutableArray arrayWithObject:delegate] retain] forKey:date];
Why not just change that to:
[calendarRequestLog setObject:[NSMutableArray arrayWithObject:delegate] forKey:date];
Write instead
calendarRequestLog = [[NSMutableDictionary alloc] init];
this
self.calendarRequestLog = [NSMutableDictionary dictionary];
and try to use property instead ivar

Resources