EXC_BAD_ACCESS only on device when allocating an object - ios

I am getting EXC_BAD_ACCESS error at the line
GADRequest *request = [[GADRequest alloc] init];
I don't have source code of GADRequest as its from Google AdMob SDK.
The stack trace is below.
Its happening only on device and not on simulator.
#0 0x34a80462 in objc_msgSend ()
#1 0x0017d9dc in +[GADRequest alloc] (self=<value temporarily unavailable, due to optimizations>, _cmd=<value temporarily unavailable, due to optimizations>) at /Users/mikeying/work/ios_sdk_git/googlemac/iPhone/GoogleAds/NextGen/Request/GADRequest.m:48
#2 0x0006e728 in -[AdWhirlAdapterGoogleAdMobAds getAd] (self=0x5511c0, _cmd=0x225209) at /Users/xxx/yyy/libs/AdWhirl/adapters/AdWhirlAdapterGoogleAdMobAds.m:68
#3 0x0007b4f6 in -[AdWhirlView makeAdRequest:] (self=0x5538f0, _cmd=0x22691c, isFirstRequest=1 '\001') at /Users/xxx/yyy/libs/AdWhirl/internal/AdWhirlView.m:370
#4 0x0007ac5c in -[AdWhirlView buildPrioritizedAdNetCfgsAndMakeRequest] (self=0x5538f0, _cmd=0x226965) at /Users/xxx/yyy/libs/AdWhirl/internal/AdWhirlView.m:235
#5 0x35818bbe in -[NSObject(NSObject) performSelector:withObject:] ()

The program receives the EXC_BAD_ACCESS signal when a message is sent to an object that has been deallocated. With the environment variable NSZombieEnabled set to YES, objects are never deallocated, but instead kept in memory as zombie objects. When a message is sent to a zombie object, execution stops at the line that would normally cause the EXC_BAD_ACCESS signal.
In Xcode 4.2, you could set environment variables by editing scheme, select the “Run XYZ.app” stage in the left panel, then select the “Arguments” tab on the right.
It’s important that you disable NSZombieEnabled once you’re done, or your application would use a tremendous amount of memory and eventually would crash.

Related

iOS crash - Selector name found in current argument registers: retain

In hockey app dashboard, I'm getting crashes with following hints:
Exception Type: SIGTRAP
Exception Codes: #0 at 0x1943f61e8
Crashed Thread: 7
Application Specific Information:
Selector name found in current argument registers: retain
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x568855a90
Crashed Thread: 18
Application Specific Information:
objc_msgSend() selector name: retain
Both crash groups are hitting same code but somehow they had different crash description which I believe should be same root cause.
This is what my code looks like:
thread 1:
dispatch_queue_t queue;
#synchronized (self) {
queue = _mySerialQueue;
}
dispatch_async(queue, ^{ // Crash happens here
if (_ivar) {
...
}
});
thread 2:
#synchronized (self) {
_mySerialQueue = dispatch_queue_create(...);
}
Can this code run into ARC issue?
On the premise that (please verify these)
_mySerialQueue is an instance variable
_mySerialQueue is only accessed within #synchronized(self) blocks
You don't access _mySerialQueue via any property or via key value coding ([theObject valueForKey:"mySerialQueue"])
All code you posted runs with ARC
I see only one reason why the above code could crash the way it does. I'm still not 100% sure about that, but here is my shot:
self is in the process of being deallocated when the crash happens. It can be checked if you clean the iVar in dealloc:
- (void)dealloc {
#synchronized(self) {
_mySerialQueue = nil;
}
// ...
}
these crashes would be extremely rare, e.g. one in a hundred at least. If it happens more often, I think the problem is somewhere else.
After the change, the app would still crash, but the EXC_BAD_ACCESS would be at a lower memory location because you are dereferencing a NULL pointer when you call dispatch_async(nil, ...). The crash location will most likely be 0x00000050, or a similarily low address.
Why do I think this?
When an object is being destructed, the iVars are destroyed in a separate pass by a method named .cxx_destruct. When this happens, the iVar can be in the process of being deallocated, but at the same time the variable still points to the object because it is never cleared.
Important: If this works, it will just replace one rare crash with another rare crash, because it would mean that there is a race condition on self somewhere.
Another possible solution would be to try to reproduce the problem with the thread sanitizer. It can track down such problems pretty fast in most cases.

SignalR / malloc error - incorrect checksum for freed object?

I have been noticing random crashes in my application that all seem to have to do with SignalR-ObjC. The crash can occur either shortly after the SignalR data is received or after several minutes of receiving data.
The error message is:
malloc: *** error for object 0x7fbae292ce00: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
The breakpoint gets placed on this line in the SRChunkBuffer.m file:
[_buffer appendString:[[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding]];
If I comment out my code that uses SignalR-ObjC to invoke a server-side method to subscribe to groups, this crash does not occur:
for (NSString *groupName in combinedArray ){
[proxy invoke:#"Subscribe" withArgs:#[groupName] completionHandler:nil];
}
I have made sure all my cocoa pods / dependencies for SignalR-ObjC are up to date, removed my loop for registering for groups and instead manually registered for them one at a time, and yet I still get a crash randomly.
I see mentions of potentially using #synchronized but not sure how that fits into this case.
How can I stop this crash?
Resolved by replacing my [connection start] with:
[connection start:[[SRLongPollingTransport alloc] init]]
Had to import "SRLongPollingTransport.h" to make this work...
Source: https://github.com/DyKnow/SignalR-ObjC/issues/243

Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xb06b9940)

I'm new to lldb and trying to diagnose an error by using po [$eax class]
The error shown in the UI is:
Thread 1: EXC_BREAKPOINT (code=EXC_i386_BPT, subcode=0x0)
Here is the lldb console including what I entered and what was returned:
(lldb) po [$eax class]
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xb06b9940).
The process has been returned to the state before expression evaluation.
The global breakpoint state toggle is off.
You app is getting stopped because the code you are running threw an uncaught Mach exception. Mach exceptions are the equivalent of BSD Signals for the Mach kernel - which makes up the lowest levels of the macOS operating system.
In this case, the particular Mach exception is EXC_BREAKPOINT. EXC_BREAKPOINT is a common source of confusion... Because it has the word "breakpoint" in the name people think that it is a debugger breakpoint. That's not entirely wrong, but the exception is used more generally than that.
EXC_BREAKPOINT is in fact the exception that the lower layers of Mach reports when it executes a certain instruction (a trap instruction). That trap instruction is used by lldb to implement breakpoints, but it is also used as an alternative to assert in various bits of system software. For instance, swift uses this error if you access past the end of an array. It is a way to stop your program right at the point of the error. If you are running outside the debugger, this will lead to a crash. But if you are running in the debugger, then control will be returned to the debugger with this EXC_BREAKPOINT stop reason.
To avoid confusion, lldb will never show you EXC_BREAKPOINT as the stop reason if the trap was one that lldb inserted in the program you are debugging to implement a debugger breakpoint. It will always say breakpoint n.n instead.
So if you see a thread stopped with EXC_BREAKPOINT as its stop reason, that means you've hit some kind of fatal error, usually in some system library used by your program. A backtrace at this point will show you what component is raising that error.
Anyway, then having hit that error, you tried to figure out the class of the value in the eax register by calling the class method on it by running po [$eax class]. Calling that method (which will cause code to get run in the program you are debugging) lead to a crash. That's what the "error" message you cite was telling you.
That's almost surely because $eax doesn't point to a valid ObjC object, so you're just calling a method on some random value, and that's crashing.
Note, if you are debugging a 64 bit program, then $eax is actually the lower 32 bits of the real argument passing register - $rax. The bottom 32 bits of a 64 bit pointer is unlikely to be a valid pointer value, so it is not at all surprising that calling class on it led to a crash.
If you were trying to call class on the first passed argument (self in ObjC methods) on 64 bit Intel, you really wanted to do:
(lldb) po [$rax class]
Note, that was also unlikely to work, since $rax only holds self at the start of the function. Then it gets used as a scratch register. So if you are any ways into the function (which the fact that your code fatally failed some test makes seem likely) $rax would be unlikely to still hold self.
Note also, if this is a 32 bit program, then $eax is not in fact used for argument passing - 32 bit Intel code passes arguments on the stack, not in registers.
Anyway, the first thing to do to figure out what went wrong was to print the backtrace when you get this exception, and see what code was getting run at the time this error occurred.
Clean project and restart Xcode worked for me.
I'm adding my solution, as I've struggled with the same problem and I didn't find this solution anywhere.
In my case I had to run Product -> Clean Build Folder (Clean + Option key) and rebuild my project. Breakpoints and lldb commands started to work properly.

Xcode 4 break on exception or assert with good call stack AND printing of the exception

Using Xcode 4.3.2. I looked at many different similar issues including this one
no-call-stack-on-exception-in-xcode-4
but cannot get the debugger (gdb or lldb) to give me a good stack trace that shows the location of the exception AND to also prints what the exception is
Setting either a symbolic exception on objc_exception_throw or an "All Exceptions" exception breakpoint, lldb would not give me a good stack trace but would show the following:
thread #1: tid = 0x1c03, 0x34455238 libobjc.A.dylibobjc_exception_throw, stop reason = breakpoint 1.1
frame #0: 0x34455238 libobjc.A.dylibobjc_exception_throw
frame #1: 0x323ff788 CoreFoundation`+[NSException raise:format:arguments:] + 100
That is the whole thing, either through bt or at full magnification in the graphical breakpoint/debugger view.
If I hit continue a few time at this point it will eventually tell me the exception/assertion, for example
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '_endUndoGroupRemovingIfEmpty:: NSUndoManager 0x2b7610 is in invalid state, endUndoGrouping called with no matching begin
But I have no idea where it is at.
gdb, using the same breakpoint, WILL stop and show me where it is at, but does not print the exception text. If I hit continue a few times it does but I have lost my context of the back trace.
I would like to know how to print the exception text so I know WHY it stopped, without having to do a few continues and losing my place. I would also like to get it to stop in lldb at the point of the exception like it does in gdb.
Please try updating to Xcode 4.5. You're seeing an armv7 unwinder problem where lldb doesn't know how to unwind your stack completely. The Objective-C runtime has some functions that are difficult to unwind out of (hand-written assembly) but I just did a quick test on an iOS device with Xcode 4.5 and lldb behaved correctly when I had Xcode set an Exception Breakpoint on throw.

Using Zombies in Xcode

I am using Zombies to try and get rid of an EXC_BAD_ACCESS error.
In Zombies, I got this message when the app crashes -
An Objective-C message was sent to a deallocated object (zombie) at
address: 0x8955310.
My question is what do I do next to solve the problem ?
Turn on malloc stack logging and zombies for your scheme in Xcode, and run the app in the simulator. Xcode should enter the debugger when the message is sent to the zombie. Run this command at the debugger prompt:
info malloc 0x8955310
(Substitute the actual address of the zombie!) You'll get stack traces from when that address was allocated and freed.
Most likely you have created an object, released it and later sent it a message.
To make sure this won't happen, a safe practice would be to set your object to nil once you are done using it
Consider:
NSMutableArray *a = [NSmutableArray array];
[a dealloc];
[a do_something_weird];
Your app is likely crash (won't always crash) in response to this message, as after release, you don't own this memory, and it may be used by some other object.
If you change this sequence to
NSMutableArray *a = [NSmutableArray array];
[a dealloc];
a=nil;
[a do_something_weird];
Exactly nothing will happen. This is a safe practice to follow when you are sure you're done using the object.
You also may want to consider using the Automatic Reference Counting feature, which helps a lot with memory management.

Resources