Saturday, April 14, 2012

Native crashes in MonoTouch

If you use MonoTouch a bit, you will once in a while run into native crashes. In a perfect world you'd never see such a horrible thing, but unfortunately the world isn't perfect, and in real life there are several ways you can end up crashing your app. Usual debugging techniques with MonoDevelop will not work, but with some ingenuity you can figure out what's going on. And you will catch a glimpse of how the world is for those poor guys who can't develop in C#!

Now, how do you find out what happened? You need as much information as possible, and information related to a native crash is twofold:
  • Crash report.
  • Console output.

Where you can find each differs depends on whether you're running in the iOS simulator or on an iOS device.

You're running in the iOS simulator.



In this case, the console is the system console on your Mac. You can find the Console application in Applications -> Utilities -> Console. This is how it looks like:


Now let's see what happens if you crash in the simulator. You will get this dialog:


and if you click the Report button, you'll see the crash report:


The same crash report is also available in the Console, in case you dismissed the dialog:




You're running on an iOS device.



In this case, you want Xcode's Organizer. Open Xcode, and go to the Window -> Organizer menu entry.


Here you will find crash reports under the Device Logs node, and the obviously the console output will be under the Console node.

Now what?


Some times the information you found tells you exactly what happened.

This is the case for an unhandled exception, in which case you'll see something like this in the console:

13/04/12 4:28:54.101 PM CrashReporting: 
Unhandled Exception: System.Exception: Unhandled I am!
  at CrashReporting.AppDelegate.UnhandledException () [0x00000] in /Users/rolf/Projects/CrashReporting/AppDelegate.cs:27
  at MonoTouch.Dialog.StringElement.Selected (MonoTouch.Dialog.DialogViewController dvc, MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x0000b] in /mono/ios/MonoTouch.Dialog/MonoTouch.Dialog/Elements.cs:691
  at MonoTouch.Dialog.DialogViewController.Selected (MonoTouch.Foundation.NSIndexPath indexPath) [0x00029] in /mono/ios/MonoTouch.Dialog/MonoTouch.Dialog/DialogViewController.cs:518
  at MonoTouch.Dialog.DialogViewController+Source.RowSelected (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00019] in /mono/ios/MonoTouch.Dialog/MonoTouch.Dialog/DialogViewController.cs:364
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /mono/ios/monotouch/src/UIKit/UIApplication.cs:38
  at CrashReporting.Application.Main (System.String[] args) [0x00000] in /Users/rolf/Projects/CrashReporting/Main.cs:17

in this case it's pretty obvious what happened. But this isn't often the case, usually the information is at best unfamiliar unless you already have experience debugging native crashes (and in some cases the crash happens way after the underlying cause, and any relevant information is long lost. When this happens you'll have to resort to more creative debugging techniques).

I will write more blog posts describing some of the most common reasons for native crashes later, but in the mean time you have a few options to get help:


In all cases be sure to include all information you're able to gather, have in mind that even though the console output and crash reports may be greek to you, it may provide valuable information to somebody else.