131

Every time my app crashes Xcode highlights the UIApicationMain() call in the main() function as the line that caused the crash. In some cases that used to be normal (segmentation fault for example) but the crash I am trying to deal with is a simple SIGABRT with detailed information logged in the console:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: Date)'

Xcode used to show the line just right with older SDKs but since i upgraded to Xocde 4.2 that changed. It is pretty obvious that Xcode knows exactly what caused the crash (or could know), but its still not showing the actual line. Is there any fix or workaround for this?

JonasG
  • 9,274
  • 12
  • 59
  • 88
  • 2
    Are you compiling for Release? If so try setting the scheme to Debug. – epatel Oct 09 '11 at 11:10
  • It could also be that some xib is bad causing the program to crash in a place out of your own source code, thus, not showing any file. The error describes a problem for a dictionary key named "Date" – epatel Oct 09 '11 at 19:13
  • 1
    Apple should hire more testers ;) – Amr Lotfy Feb 10 '16 at 08:10

5 Answers5

307

You should also ensure that you have breakpoints set for all exceptions. This will cause Xcode to stop at the line where the exception is occurring. Do the following [in Xcode 4]:

  1. In the Project Navigator on the left side of Xcode, click on the breakpoint navigator (almost all the way to the right hand side of the top button bar. The icon looks like a fat right arrow).

  2. At the bottom of the navigator, click the "+" button.

  3. Click "Add Exception Breakpoint".

  4. A new breakpoint will be created. It should be configured as needed but you can tweak its behavior.

  5. Run your project and reproduce the exception.

Also you mentioned that you linked to some 3rd party libraries/frameworks. If the exception is occurring within those frameworks then you are going to have a hard time since the code is compiled and Xcode can't actually show you the line that caused the exception. If this is the case and you are certain you are using the libraries correctly, then you should file a bug report to the maintainers of those libraries.

Carter
  • 4,738
  • 2
  • 22
  • 24
  • No, choose "On Throw", else it will catch the breakpoint on main. – Doug Smith Jun 08 '13 at 16:59
  • 4
    I am a noob and developed almost a month without this... this changes my life. – Jonny Burger Mar 17 '14 at 15:04
  • 5
    My friend registered for a S.O. account just to upvote this post. – Alex Spencer Jul 11 '14 at 07:09
  • 1
    this is called half assing on apples part in my book – ChuckKelly Jul 21 '14 at 02:02
  • 1
    Did this but still can't find where it called length on a null :( – Shereef Marzouk Sep 09 '14 at 10:22
  • 1
    This works, but the downside is it not longer outputs details of the exception in the debug console. So I can turn OFF this breakpoint, and see details and trace of the exception but not WHERE it happened, or turn it ON to see where it happened, but with not WHY. Anyone know how to have both? – Gabriel Jensen Oct 01 '14 at 20:56
  • This answer is the most amazing thing I've seen for a while, thanks! – alper_k Jan 14 '15 at 12:30
  • Nice and simple! This works perfectly on Xcode 6.1 also. – Alejandro Cotilla May 30 '15 at 03:39
  • @GabrielJensen pressing the `continue program execution` button (maybe more than once) will give you the exception details just like when the breakpoint is not set. – GraehamF Jun 28 '15 at 16:45
  • Why should I have to "reproduce the exception"???? That's completely unreasonable and a waste of my time. Tell me the first time it crashes. There are crashes where reproducing are VERY non trivial. Dear Xcode, What a great IDE you are. If you have a bug, all I have to do is restart you and there's a 50% chance the bug is fixed. – jgvb Jun 30 '15 at 15:30
  • It does not work with `fatal error: unexpectedly found nil while unwrapping an Optional value` – vkalit Feb 01 '16 at 12:54
  • 1
    I tested this solution in Xcode 7 and it worked perfectly. But shouldn't this be done automatically by Xcode? – Milad.Nozari Jun 29 '16 at 13:36
  • 1
    You absolute legend! I can't believe how long I've spent debugging apps without knowing this. – Scotch Design Jul 28 '16 at 11:36
  • Incredible! This used to be default behaviour, but I've wasted years throwing NSLog everywhere to track down the point at which crashes occur. This has changed everything :D – mashers Apr 13 '17 at 15:15
  • Lifesaver! I removed all breakpoints at once, took the default exception handler with me! – gilm Feb 05 '19 at 19:52
28

Simply follow the instructions on this StackOverflow answer:

Enable Zombies

Basically, you just need to "Enable Zombies". Then Xcode should break at whichever line caused the problem.

enter image description here

(It is absolutely shocking that, even in 2017, Xcode still has this turned off by default. Why would you not want to see the line that caused the problem ? And "Enable Zombie Objects" ?! Really ?! Do the Xcode authors really believe that this is a useful name, which would make any kind of sense to new developers ? It is depressing how poor Xcode's rating is, year after year, in the App Store. No one is listening...)

Community
  • 1
  • 1
Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159
  • 11
    Xcode is the worst programming environment I used so far. – Student Jun 13 '18 at 06:20
  • What I find interesting (as a Visual Studio developer) is how many Xcode developers I've met, who insist that Xcode is the best environment they've ever used. Logical, friendly and helpful.. but with a few quirks. Even now, in November 2019, Xcode has an App Store rating of 3.1, with most people giving it 5-stars or 1-star. No one is listening.... – Mike Gledhill Nov 17 '19 at 13:04
10

Edit the current scheme and enable NSZombieEnabled, MallocStackLogging, and guard malloc. Then, when your App crashes, type this in the gdb console:

(gdb) info malloc-history 0x543216

Replace 0x543216 with the address of the object that caused the NSInvalidArgumentException and it should give you a much more useful stack trace, showing the lines of your code that are causing the crash.

chown
  • 51,908
  • 16
  • 134
  • 170
  • 1
    I tried this, and was thrown the error: 'info' is not a valid command. Any advice? – esreli Mar 07 '13 at 00:14
  • @EliGregory make sure your debugger is set to gdb and not the default lldb. You can change it in the Edit Scheme menu under the run section. – chown Mar 07 '13 at 03:41
2

I have seen this behavior in heavily optimized code; checking,tweaking your target's optimization level and those of 3rd party libs may help. (LLVM 3.0 Optimization level setting)

Are you generating debug symbols?

FluffulousChimp
  • 9,157
  • 3
  • 35
  • 42
  • Agreed. If you are trying to debug then the optimization level needs to be set to 0 (No Optimization) in your build settings. – Carter Apr 20 '13 at 00:47
1

I wrote code to generate a crash of index out of bound. Following is the exception thrown.

2017-01-07 04:02:57.606 testABC[1694:52966] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010e85cd4b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010e2be21e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010e8b5c2f -[__NSSingleObjectArrayI objectAtIndex:] + 111
    3   testABC                             0x000000010dce962d -[ViewController ComplexFunction] + 61
    4   testABC                             0x000000010dce95db -[ViewController thirdFunction] + 43
    5   testABC                             0x000000010dce959b -[ViewController secondFunction] + 43
    6   testABC                             0x000000010dce955b -[ViewController firstFinction] + 43
    7   testABC                             0x000000010dce96c2 -[ViewController viewDidAppear:] + 50
    8   UIKit                               0x000000010ee28a6c -[UIViewController _setViewAppearState:isAnimating:] + 945
    9   UIKit                               0x000000010ee2b7da __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke + 42
    10  UIKit                               0x000000010ee29ac4 -[UIViewController _executeAfterAppearanceBlock] + 86
    11  UIKit                               0x000000010ec8d77c _runAfterCACommitDeferredBlocks + 653
    12  UIKit                               0x000000010ec7a273 _cleanUpAfterCAFlushAndRunDeferredBlocks + 566
    13  UIKit                               0x000000010ec9d757 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke_2 + 194
    14  CoreFoundation                      0x000000010e8016ac __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    15  CoreFoundation                      0x000000010e7e66f4 __CFRunLoopDoBlocks + 356
    16  CoreFoundation                      0x000000010e7e5e65 __CFRunLoopRun + 901
    17  CoreFoundation                      0x000000010e7e5884 CFRunLoopRunSpecific + 420
    18  GraphicsServices                    0x00000001126d9a6f GSEventRunModal + 161
    19  UIKit                               0x000000010ec80c68 UIApplicationMain + 159
    20  testABC                             0x000000010dce99df main + 111
    21  libdyld.dylib                       0x000000011174968d start + 1
    22  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

If you read carefully the First Throw call stack

0   CoreFoundation              0x000000010e85cd4b __exceptionPreprocess + 171
1   libobjc.A.dylib             0x000000010e2be21e objc_exception_throw + 48

0 and 1 are the system processes after crash.

 2   CoreFoundation             0x000000010e8b5c2f -[__NSSingleObjectArrayI objectAtIndex:] + 111

2 is the line which caused the exception.

3   testABC                     0x000000010dce962d -[ViewController ComplexFunction] + 61

3 tells you that Class name (ViewController) and function naem (ComplexFunction) in which exception was thrown.

AsifHabib
  • 944
  • 9
  • 25
  • 5
    Errr, okay. You're absolutely right, but is this friendly ? In any modern (1990s onwards) development environment, when an exception occurs, you are taken to the line which caused the problem. Whereas Xcode... well... gives you a stack trace like this. Even Turbo Pascal wasn't this outdated !!! – Mike Gledhill Jan 27 '17 at 10:19
  • 8
    It's ridiculous that the company that's supposedly known for the "best user experience" doesn't realize that all developers for the last 20 years are accustomed to seeing the line number where an exception is thrown and NOT IN ASSEMBLER. Am I going insane? Every language I've ever worked with my entire life gives line numbers. Even C or C++. – mylovemhz Dec 19 '17 at 21:49