Unable to determine what is going on with this error.
I am uploading a file in multiple segments.
I have threaded my api calls into 7 concurrent threads.
Here is the assembly code that it stops at.
Here is my printed stack trace
Finally the Stack window
I do not have any DISPATCH_QUEUE_PRIORITY_LOW except for a #define for dispatch_get_low() and I do not have any calls to dispatch_get_low()
as a little background, I am developing my app from xcode 4.4 and recently installed GM Seed 4.5 to test on ios 6. All of my code is still ios5 and this bug plagued me before and after the update of xcode.
UPDATE
After adding back NSZombieEnabled YES to my environment variables
I was presented with a different error in much the same fashion, This one however is called forwarding
Assembly breakpoint
Stack Trace Printout
Call Stack Window
I am still at a loss as to what is actually going on.
I am still investigating. any further assistance will be much appreciated.
==== New Developments ====
Apparently while trying to get some output of the malloc calls. I completely alleviated the bug.
This is disheartening because I dont think I can compile for release with this flag enabled.
the EXC_BAD_ACCESS no longer appears, therefore the log is going to be useless. This bug is turning out to be the weirdest problem I have faced yet, And I have faced a lot of weird iOS bugs.
Update again
I have been tracking this error down. Turns out the object being a problem is a -[CFNumber release] call The number is being created in a block, then being passed down to the delegate.
It may also be combined with the Core Data object saving and then going away.
I have added a method HSLogBrute(#"") which logs the line number and filename.
I have tracked it down to the following code.
if (progressMatch > progressPercent){
HSLogBrute(#"");
TransferStatus *transferStatus = [TransferStatus objectByID:task.transferStatusID];
HSLogBrute(#"");
transferStatus.segmentsTransferred = [NSNumber numberWithInt:segmentsTransferred.intValue];
HSLogBrute(#"");
transferStatus.segmentsTotal = [NSNumber numberWithInt:segmentsTotal.intValue];
HSLogBrute(#""); // This is the last log I am getting.
[transferStatus save];
HSLogBrute(#"");
}
HSLogBrute(#"");// Before putting in the [NSNumber numberWithInt:] calls this was the last line.
Turns out we were creating an NSMutableDictionary and using numbers within it. Creating and Destroying NSNumbers as fast as we were doing seems to have confused arc at some point. And the objects were being retained and released out of order.
My solution has been to create a custom object that has the numbers that I need within it. And increment and decrement those primitive number types rather than create and destroy so many NSNumber values.
Related
I made a breakpoint in Xcode with the jump commend to force passing some condition, but when it execute to line 168 it crash with message
"Thread 1: EXC_BAD_ACCESS (code=1, address=0x1)"
why did that happen?
the console logged:
warning: MoreMultitypeCollectionViewCell.swift:178 appears multiple times in this function, selecting the first location:
MoreMultitypeCollectionViewCell.(updateButtonStateCkeck in _9A12557DCAB30EEB52DC7C2EA09487CD)() -> () + 1580 at MoreMultitypeCollectionViewCell.swift:178
MoreMultitypeCollectionViewCell.(updateButtonStateCkeck in _9A12557DCAB30EEB52DC7C2EA09487CD)() -> () + 1600 at MoreMultitypeCollectionViewCell.swift:178
my questions are:
How should I type in lldb to select location?
Is there a better way to force passing into If Statement without change code and rebuild project?
sometimes when I type 'po' in lldb or click print description in variable view, it will show fail message, how is that?
1) In lldb, the equivalent command is thread jump and you can specify an address as well as a line number there.
2) thread jump or the Xcode equivalent is an inherently dangerous operation. If you jump over the initialization of some variable, you will be dealing with bad data now and will likely crash. That sort of thing you can sometimes spot by eye - though Swift is lazy about initialization so the actual initialization of a variable may not happen where you think it does in the source. There are more subtle problems as well. For instance, if you jump over some code that as a byproduct of its operation retains or releases an object, the object will end up under or over retained. The former will cause crashes, the latter memory leaks. These retains & releases are generated by the compiler, so you can't see them in your source code, though you could if you look at the disassembly of the code you are jumping over.
Without looking at the code in question, I can't tell why this particular jump caused a crash.
But you can't 100% safely skip some of the code the compiler choose to emit. Looking at the disassembly you might be able to spot either (a) a better place to stop before the jump - i.e. stop past some retain or release that is causing a problem or jump to an address in the middle of a line so you still call a retain that's needed. You'll have to figure this out by hand.
3) There's not enough info to answer this question.
BTW, your image links don't seem to resolve.
I have an NSMutableArray of UIImageViews which I iterate through continuously (using a CADisplayLink). I do this to continuously move the UIImageViews around the screen.
When I remove a UIImageView from the array, I sometimes get the error:
EXC_BAD_ACCESS (code=1, address=0x20000008)
However I use to get the error "Array was mutated while being enumerated" in the past before I started using ARC/iOS6 so I think these two errors mean exactly the same thing but i'm not sure.
Anyway here is my question. Removing a UIImageView from the array using any of the following methods gives me the error stated above.
[imageViews removeObject:imageView];
[imageViews performSelector:#selector(removeObject:) withObject:imageView];
[imageViews performSelectorOnMainThread:#selector(removeObject:) withObject:imageView waitUntilDone:YES];
However, using any of the methods below never gives me the error.
[imageViews performSelectorOnMainThread:#selector(removeObject:) withObject:imageView waitUntilDone:NO];
[imageViews performSelector:#selector(removeObject:) withObject:imageView afterDelay:.01];
So can someone explain to me why removing an object from an NSMutableArray using the first set of methods listed above gives me what I believe is a "Array was mutated while being enumerated" error, while using the second set of methods NEVER gives me that error?
I have been using the second set of methods listed above all the time to get around this error (and everything works perfectly if I use them) but I would like to know exactly why my problem is resolved when I use them and if it is safe to use one of those two methods.
This is my first time posting a question so forgive me if I am posting this the wrong way.
Because CADisplayLink calls back on a background thread, it's entirely possible that by scheduling the array in question to remove a given object from said thread, that another is in the process of mutating or enumerating the array, which throws the exception. The top two methods don't work because they require synchronized access to the array (which NSMutableArray doesn't provide), and they schedule in the run loop of the current thread, rather than the main thread, so their respective executions are not guaranteed to not access the same resource at the same time. The bottom two work because, assuming you're mutating the array on the main thread, it is impossible for that run loop to schedule the instruction to enumerate and the instruction to mutate concurrently (one thread can't run two pieces of code at the same time, especially when that code is scheduled in the next iteration of the run loop), so the array is much safer to access. By using a delay, you create a race conditions, which for you has worked so far, but will come back to haunt you at a later date.
When you enumerate through an array (step through it with a for … in … loop or use an NSEnumerator) the enumeration requires that you do not alter the array at all during the loop itself or on another thread at the same time (hence the original warning).
I don't know why the bottom two methods work - I would guess internally that they alter the array in a way that does not effect the enumeration.
Having said that, it's bad practice and I would not recommend altering an array during it's enumeration in any way whatsoever. Even if it works today, it may not tomorrow. What I would recommend is storing the indexes to be removed until after the enumeration, then remove them as in this answer.
With reference to the question here.
The solutions provided in that thread, include:
Being smart about where and how many variables you declare, that would go on the stack.
Disable Guard Malloc if needed.
Also, in general:
3. Make sure you are releasing a variable you have actually allocated memory for!!
I have none of the above issues. There are very few stack-allocated variables that I use within functions, say 2-3 within each. But because the functions are called in a loop several times, it seems to trigger an exception.
And here's the kicker, this is not just happening for statically allocated variables, but stuff on the heap too! I'm getting the page errors on Auto-released declarations of NSNumber variables that I use a couple of inside the loop, as well as a dictionary that I juDIciously alloc and release within the scope of the function, every single time it's called.
So why is this happening, and why the heck are heap variables getting affected? I don't get it at all, please throw some light on this. :)
I'm on IOS5 with XCode 4.2, iPhone/iPad simulator.
Thanks!
Regards,
Dev
Edit: Sample code
- (void)doSomething {
NSInteger fun = 3;
NSInteger time = 4;
NSInteger overload = fun*time;
NSString *string = [NSString stringWithFormat:#"%d",overload];
NSObject *myCustomObject = [[NSObject alloc] init];
[myCustomDictionary setObject:myCustomObject forKey:string];
[myCustomObject release];
//myCustomDictionary is an iVar, alloced in the class's init method, and released in dealloc and not touched anywhere in between
}
//doSomething gets called several times through the course of execution as the state of the view changes, the user interacts with it etc, often 2-3 times during one state change.
The code is purposely vague, but at the same time, it is EXACTLY as simple as in the sample. As is the rest of the code in the entire project. Several functions, each doing a small amount of work, as nicely self contained memory-wise as this one.
I faced EXC_BAD_ACCESS issues before, and at that point had referred to this question. However in my case, I was not creating multiple variables on the stack within a loop, they were getting created repeatedly by a function which gets called several times through the course of the execution. Ideally, the variables should have just got destroyed at the end of function-scope. Not sure why that didn't happen.
Anyway, to resolve that and to prevent multiple allocations from happening, I ended up declaring my stack-allocated variables as all static. That is bad practice, but that's exactly what I had to do to get it working. And it was working until I ended up facing the issue AGAIN with the "doSomething" function.
So the difficulty in "doSomething", was that I did not have only stack-allocated variables getting created, but heap stuff too. So I first started getting EXC_BAD_ACCESS on the NSInteger variables, at which point I tried fixing it again, by declaring them as static. It worked, but now EXC_BAD_ACCESS started occurring on the auto-released variable and finally the custom-allocated variable - which is when I got stumped. I have been following all the rules of memory management, and I'm having stack AND heap variables fubaring all over me. If it was only heap stuff, or stack stuff inside a loop, I could understand there's a mistake SOMEwhere. But here, it's neither, these are perfectly innocent variables getting allocated on the stack inside ONE function that is NOT called in a loop, and regular auto-released variables that never ever get retains or releases thrown at them from another place in the code. What makes it all even worse, is that the failure points are random - not just in this function but practically every one that gets called several times through the course of execution of the project.
Edit2: Turns out, in this case, it's my fault. See my answer for details. Sorry for wasting people's time. :\
We can't really help you without seeing the whole stack trace.
EXC_BAD_ACCESS doesn't mean anything in order to troubleshoot we need to know what the exception is.
Based on my experience when you don't get a stack tarce it means you are double releasing. Zombies is the way to find your double release.
Go to: Product -> Profile and then select "Zombies" from the list.
Run the app and perform any task that causes the crash, if the problem is a double release a pop-up would appear. Select the arrow in the popup and it tells you exactly what object is being double released, and it shows you the retain cycle.
Without any code posted in your question, and seeing that you are using iOS 5 and Xcode 4.2 my best advice for you is, in Xcode, go to Edit>Refactor>Convert to Objective-C ARC and wave all your memory management headaches goodbye.
ARC does all the memory management for you. You do not need to retain, release or write dealloc methods. You don't have to worry about memory management in most cases. You will leave mysterious EXC_BAD_ACCESS crashes behind. The way it works is super efficient. The compiler puts in the retains and releases for you and then optimises. You never even have to see the code.
Ah geez I don't believe this.
The issues faced earlier with the stack-allocated NSInteger variables holds, but in this case, it was entirely my fault.
"doSomething" was part of a long chain of events, that, due to some silly negligence on my part, ends up looping a bunch of times, which is what, rightfully and as it should be, leads to the application running out of memory. Whether it's with the stack variables or with the malloced ones sitting on the heap, with an infinite loop, it's gonna crash one way or another. :)
So the crash is perfectly fair, just got confused in this case with a previous issue that turned out to be unrelated. :(
Sorry for wasting everybody's time.
I have a pretty weird problem in my iPhone app which is, I think, related to memory getting corrupted:
At one point, I need to sort an array, which I do with -[sortArrayUsingFunction].
The result is not correct unless I either allocate some memory with something like void *test = malloc(2 * sizeof( int )) before the method call or have, e.g., a call to NSLog() (which is never invoked) in the sorting function.
In other words: the sorting only works if I slightly increase the memory that was used before calling the sorting function. I think this is because at some point, memory gets corrupted.
How do you debug something like this?
It sounds like some of your code is using already released objects. A lot of help with debugging this kind of errors is provided in Apple’s great Mac OS X Debugging Magic tech note, especially the foundation part.
For your case I'd disable autorelease pools (setting the environment variable NSEnableAutoreleasePool=NO) or use the zombie feature (NSZombieEnabled=YES) to find places where you send messages to released objects.
Try running your program in the simulator under Valgrind:
http://valgrind.org/
And how to use it under the simulator:
http://landonf.bikemonkey.org/code/iphone/iPhone_Simulator_Valgrind.20081224.html
You may have to change the VALGRIND path in the code example depending on where it gets installed.
Such things can be a challenge to debug. There are some tools for detecting out-of-bounds accesses and such on other platforms, so I presume there would be something for the iPhone, however I don't know of any.
Perhaps you should store two copies of the array, and compare them for differences. Print out the differences. The nature of the "junk" that was introduced to one of the arrays might give a hint as to where it came from.
Also just go through the code that runs before this point, and re-read it (or better yet, get someone else to read it). You might spot a bug.
Ok so this is gonna be a bit of a shot in the dark without you being able to see my application!
I have a bug. I have a SwimmingPool class, my app passes the pool from a tableview into a detail view where you can see all the swimmingPool class fields. You can then click on the individual detail, edit it, and then save it. The 'original' pool facility is copied and passed to the view controller responsible for actually making changes. If the user presses save, the fields are copied from the copy into 'original'
switch (self.sectionFromParentTable) {
case KNameIndex:
self.thePoolFacility.name = self.thePoolFacilityCopy.name;
self.thePoolFacility.type = self.thePoolFacilityCopy.type;
break;
case KAddressIndex:
self.thePoolFacility.address = self.thePoolFacilityCopy.address;
break;
case KPhoneNumberIndex:
self.thePoolFacility.phoneNumber = self.thePoolFacilityCopy.phoneNumber;
break;
case KWebAddressIndex:
self.thePoolFacility.webAddress = self.thePoolFacilityCopy.webAddress;
break;
case KPricesIndex:
self.thePoolFacility.prices = self.thePoolFacilityCopy.prices;
break;
case KPoolIndex:
self.thePoolFacility.pools = self.thePoolFacilityCopy.pools;
default:
break;
}
[self.navigationController popViewControllerAnimated:YES];
Can I have some guesses at a bug that does the following:
The bug results in the changes done
to a class' fields not being saved. In particular a class called TimeEntry, in a mutable array called Monday in a Dictionary called TermTimes in a class called pool and then in a mutable array called Pools.
It's appears random. Sometimes it
works perfectly. Sometimes it
doesn't! I can't recreate the error,
only if I'm lucky can i get it not
to save. My hunch is it could be
time sensitive. For example, If I am
entering a timetable for Pool
opening times, if i quickly add a
few entries and save it usually
works fine. If I fill in a whole
timetable then it more than not
doesn't save.
The app doesn't crash.
It's infuriating the try and debug an error that seems to happen at random. Any hints on such an epic bug hunt?
One of the best ways to tackle this type of problem (where it seemingly can't be reproduced reliably) is to insert logging code in various areas where you expect certain things to be happening. Log places that errors could occur, log what values you are expecting and what you have, etc. Next, try, try, try until you can reproduce the bug.
Unlike before, you now have a log to look at and see where things went wrong. If things still look correct everywhere, insert some more logging code elsewhere. If you see something go wrong, but don't understand it, put more logging code in that area and keep narrowing the problem down.
Hopefully this will lead to new hypotheses about how the bug happens, and you will be able to reproduce it under the debugger reliably and fix it!
As duffymo mentioned, multithreading could be the culprit, and would be a good place to investigate first if you're knowingly using multiple threads.
"random" and "hard to reproduce" makes me think that this is an issue having to do with multi-threading. Race conditions are very hard to reproduce and debug. You'll need to make sure that you have exclusive rights to the resources you need to perform this operation.
My suggestion is to look for nils. Any method call on a nil object simply does nothing and returns nil, so any time you're expecting a method to be called and it isn't, you should look for that. (.foo = is the same as setFoo:, so nil.foo = 1; will do nothing.)
Thanks for all your answers. It's now fixed.
For those interested I'd forgotten to add a cellidentifer in the XIB of my cell subclass.
cellForRow: method was therefore creating a new cell every time. The memory got filled up very quick. It then seemed as though my app was automatically trying to cut the fat by forcing another tableView out of editing mode and not managing my instances properly.
Again it's a memory problem. Isn't this always the case!?!
The clue was a one off 101 error in the console indicating my app was using too much memory. Oh and a slow scrolling tableView.