Why does assert simply terminate a program compiled for iPhone?

Seva Alekseyev picture Seva Alekseyev · Jan 4, 2010 · Viewed 12.8k times · Source

I'm debugging a heavily assert()'ed iPhone app (Xcode, Objective-C++, and device simulator). In some cases, the assert failure would just terminate the app, instead of breaking into the debugger as I'd expect.

I made a workaround by implementing my own kinda-assert to the effect of:

#define AssertLite(b) if(!(b)) {asm {int 3}}

(fluff omitted), but I wonder if anyone ever encountered this. I could not determine a pattern as to when does it break and when does it terminate. The code is not threaded; all it does is done in event handlers.

Why does this happen and how do I make vanilla assert() behave like a conditional breakpoint it should be?

Answer

Michael Taylor picture Michael Taylor · Jan 5, 2010

First off, since you are working on an iPhone app, you should probably use NSAssert() instead of the vanilla BSD assert function.

e.g. NSAssert(the_object, @"NIL object encountered");

The NSAssert macro will throw an Objective-C exception (NSInternalInconsistencyException) if the assertion fails.

Since your goal is to break on the exception, the next step is to make the Xcode debugger break on Objective-C exceptions. This is probably a good thing to do anyway.

In the Breakpoints window (Run->Show->Breakpoints menu item), click where it says "Double-Click for Symbol" to enter the symbol -[NSException raise]

The last thing to be careful off is that NSAsserts do not compile out in a release build. That means that you have to either be prepared to handle the exception in your application, or you need to create your own macro that does compile out in release builds.

Here's the macro I use to compile out assertions in runtime code (note that I then use HMAssert in my code instead of NSAssert):

#ifdef DEBUG
#   define HMAssert(A,B) NSAssert(A,B)
#else
#   define HMAssert(A,B)
#endif

This requires a DEBUG preprocessor macro to be defined. Here's how to set that up:

  1. Right-click on your project in Xcode. That will be the top item in the left panel where your projects files are listed
  2. Select "Get Info" from the context menu that pops up.
  3. Go to the "Build" tab.
  4. Make sure the "Configuration" is set to "Debug".
  5. Type DEBUG into the field next to "Preprocessor Macros" under "GCC 4.2 - Preprocessing".