5

I have a very peculiar issue.

Recently I added 64bit support to my iOS project (arm64), ever since doing that I started receiving uncaught exceptions for segments of my code inside @try...@catch (I'm using Crashlytics for crash reporting). I managed to reproduce the problem with the following lines of code anywhere in my app (I wrote them inside init of one of my view controllers):

@try {
    NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
    NSString *s;
    m[s] = @"poop";
} @catch (NSException *e) {
    NSLog(@"POOP");
}

The exception gets caught by the UncaughtExceptionHandler instead of the @catch clause. I'm confused as to what can cause this. The output in the console:

2015-02-22 19:19:53.525 [391:30650] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: key cannot be nil'
*** First throw call stack:
(0x18823a59c 0x1989400e4 0x1881251f8 0x10011e2f4 0x10011e068 0x10010e480 0x10010db78 0x10010d944 0x1000a8050 0x100075d88 0x100075160 0x100142044 0x100141f6c 0x18c9ecaa0 0x18caa1fb4 0x18caa1eb0 0x18caa134c 0x18caa0ff8 0x18caa0d18 0x18caa0c98 0x18c9e9648 0x18c341994 0x18c33c564 0x18c33c408 0x18c33bc08 0x18c33b98c 0x18cc76dbc 0x18cc77c68 0x18cc75dec 0x1904b162c 0x1881f2a28 0x1881f1b30 0x1881efd30 0x18811d0a4 0x18ca573c8 0x18ca523c0 0x1000747d8 0x198faea08)
libc++abi.dylib: terminating with uncaught exception of type NSException

I tried removing the custom exception handler that I have and disabling Crashlytics, still no success.

As soon as I remove arm64 from ARCHS and VALID_ARCHS the code works and the exception is caught as expected.

Any information will be appreciated!


Small update - our XCTests also started not to catch exceptions, up until now the behaviour only happened on physical 64bit phones.

Nimrod Gutman
  • 1,027
  • 1
  • 10
  • 21
  • Exception handling changed semantics between 32 bit and 64 bit. That could should technically still work, probably. You could "fix" it by using `@catch (id e)`. But don't; using exceptions for flow control -- for trying to recover from errors -- is not an acceptable pattern in iOS. – bbum Feb 22 '15 at 18:30
  • 1
    @bbum I'm not using exceptions for flow-control, this is a question about the difference between 32bit and 64bit and why the behaviour of the @try..@catch is different. using `@catch (id e)` or `@catch (...)` is not working either. – Nimrod Gutman Feb 22 '15 at 19:05
  • Ok -- odd, then. @gparker would know. – bbum Feb 23 '15 at 17:30
  • @bbum `@catch (id exception) {}` is not working on iPhone 6 with version 8.1.2 – MilanPanchal Oct 19 '15 at 18:19

2 Answers2

4

After a long session of git-bisecting the culprit was the following linker flag

-no_compact_unwind

I Used BlocksKit v2.2.0 which still had that flag even though it stopped using libffi (latest version of BlocksKit removed that unneeded flag). As soon as I removed that linker flag 64bit @try...@catch blocks started to work again.

I still don't have complete understanding of why this behaviour happens but I'm going to dig a bit more and update this thread if I find anything interesting.

phew

Nimrod Gutman
  • 1,027
  • 1
  • 10
  • 21
  • can you explain in details? Where to add/remove above flag? As I tried in `Other Linker Flags` but its not working. Pls help – MilanPanchal Oct 19 '15 at 18:20
  • 1
    @milanpanchal the flag was added by `libffi`, I think I manually removed that flag from `libffi` pod project but today `BlocksKit` do not require `libffi` so you shouldn't have problems. Try doing `git grep no_compact_unwind` to find where you use it – Nimrod Gutman Oct 21 '15 at 13:36
  • @kimimaro this is related to the flag (`-no_compact_unwind`) which AFAIK drops the ability to unwind the stack and find an exception handler. The flag is not super documented so I'm not 100% sure on its exact behaviour. – Nimrod Gutman Apr 06 '16 at 08:00
0

On iOS and Objective-C Exceptions are only to be used for un-recoverable programming errors, not for program execution control.

In particular they do not handle catches accross stack frames inthe APIs.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • 4
    I'm not using exceptions for execution/flow control. This is a question about the behaviour change between 32bit and 64bit. – Nimrod Gutman Feb 22 '15 at 19:06