1. クラッシュログファイルを探す
iOSアプリがデバイス上でクラッシュしたとき、デバイス上に自動でクラッシュログが生成されています。これを使えば、デバッガで接続していない状態でクラッシュした時でも、クラッシュの原因を調べることができます。
クラッシュログは、アプリがクラッシュしたデバイスを一度iTunesでMacかPCに接続して同期すると、デバイスから次の場所にコピーされます。
Macの場合:
~/Library/Logs/CrashReporter/MobileDevice
Windows Vista/7の場合:
C:\Users\<user_name>\AppData\Roaming\Apple computer\Logs\CrashReporter/MobileDevice
Windows XPの場合:
C:\Documents and Settings\<user_name>\Application Data\Apple computer\Logs\CrashReporter
これらの下に、デバイスごとのディレクトリがあり、その下に*.crashというファイルが生成されます。
例えば私のつくっているSimpleWeightというアプリがiPod1というデバイスでクラッシュしたときのログはこんな感じ。
~/Library/Logs/CrashReporter/MobileDevice/iPod1/SimpleWeight_2011-10-17-234954_iPod1.crash
このファイルをテキストエディタで開いてみると、中身はこんな感じでした。
Incident Identifier: CAF9ED40-2D59-45EA-96B0-52BDA1115E9F CrashReporter Key: 30af939d26f6ecc5f0d08653b2aaf47933ad8b8e Process: SimpleWeight [12506] Path: /var/mobile/Applications/60ACEDBC-600E-42AF-9252-42E32188A044/SimpleWeight.app/SimpleWeight Identifier: SimpleWeight Version: ??? (???) Code Type: ARM (Native) Parent Process: launchd [1] Date/Time: 2011-10-17 23:15:41.678 +0900 OS Version: iPhone OS 3.1.3 (7E18) Report Version: 104 Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: KERN_PROTECTION_FAILURE at 0x00000059 Crashed Thread: 0 Thread 0 Crashed: 0 UIKit 0x332b98d8 0x331b2000 + 1079512 1 UIKit 0x3321d1a8 0x331b2000 + 438696 2 UIKit 0x3321d028 0x331b2000 + 438312 3 UIKit 0x332b9628 0x331b2000 + 1078824 4 UIKit 0x33209d70 0x331b2000 + 359792 5 UIKit 0x33209c08 0x331b2000 + 359432 6 QuartzCore 0x324cc05c 0x324ae000 + 122972 7 QuartzCore 0x324cbe64 0x324ae000 + 122468 8 CoreFoundation 0x3244f4bc 0x323f8000 + 357564 9 CoreFoundation 0x3244ec18 0x323f8000 + 355352 10 GraphicsServices 0x342e91c0 0x342e5000 + 16832 11 UIKit 0x331b5c28 0x331b2000 + 15400 12 UIKit 0x331b4228 0x331b2000 + 8744 13 SimpleWeight 0x00002c3a 0x1000 + 7226 14 SimpleWeight 0x00002c04 0x1000 + 7172... (以下略)
デバイスの情報に加えて、クラッシュしたときのスレッド毎のスタックトレースが出力されているようですが、これだけではどこでクラッシュしたのか全くわからなくて役に立ちませんね。。。
2..dSYMファイルを探す
クラッシュしたアプリをXcodeでビルドしたときのビルドフォルダの下に、[アプリ名].app.dSMYというファイルがあり、ここにシンボルの情報が保存されていて、これを使うと、上のクラッシュログのシンボルを解決することができます。
Xcode 4のビルドフォルダは、デフォルトでは、
~/Library/Developer/Xcode/DerivedData
の下にあります。(実際の場所は、XcodeのPreferences... -> Locations -> LocationsのDerived Dataで確認できます。)
ちょっと探しにくいですが、DerivedDataフォルダの下で.dSYMを検索するのが早いかも。
% cd ~/Library/Developer/Xcode/DerivedData % find . -name '*.dSYM'
または、XcodeのProductsの下にできるアプリの実行ファイルを右クリックして、"Show in Finder"で実行ファイルの場所を開き、そこから遡って探していくのもよいかも。
今回の例では、次の場所にありました。
~/Library/Developer/Xcode/DerivedData/SimpleWeight-aahmlrjpobenlsdvhjppcfqhogru/ArchiveIntermediates/SimpleWeight/BuildProductsPath/Release-iphoneos/SimpleWeight.app.dSYM
この*.dSYMファイルがないと、クラッシュログの解析が難しくなってしまいますので、特にリリースしたビルドの*.dSYMファイルは必ずとっておくようにするべきです。私はいつもAppStoreにサブミットするビルドの直後にスナップショットをとるようにしています。
3. "symbolicatecrash"スクリプトを実行して、シンボルを解決する
.dSYMファイルを使ってクラッシュログのシンボルを解決するスクリプト"symbolicatecrash"が、Xcodeに付属しています。
私の環境(Xcode 4.2)では、次の場所にありました。
/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash
この場所にパスが通っていない場合は、パスに追加しておくか、パスが通っている場所にスクリプトをコピーするかしておくとよろしいかと思います。
- クラッシュログファイル(*.crash)
- dSYMファイル
- symbolicatecrashスクリプト
の3つがそろったら、ターミナルから次のコマンドを実行すると、シンボルを解決した結果がコンソールに出力されます。
% symbolicatecrash [クラッシュログファイル] [dSYMファイル]
例えば、上の例のクラッシュログは、
% symbolicatecrash SimpleWeight_2011-10-17-231541_iPod1.crash SimpleWeight.app.dSYM
を実行して、次のように解決されました。(結果が出力されるまでちょっと時間がかかるので、気長に待ちましょう。)
Thread 0 Crashed: 0 UIKit 0x332b98d8 -[UIWindowController transitionViewDidComplete:fromView:toView:] + 668 1 UIKit 0x3321d1a8 -[UITransitionView notifyDidCompleteTransition:] + 160 2 UIKit 0x3321d028 -[UITransitionView _didCompleteTransition:] + 704 3 UIKit 0x332b9628 -[UITransitionView _transitionDidStop:finished:] + 44 4 UIKit 0x33209d70 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 284 5 UIKit 0x33209c08 -[UIViewAnimationState animationDidStop:finished:] + 60 6 QuartzCore 0x324cc05c _ZL23run_animation_callbacksdPv + 440 7 QuartzCore 0x324cbe64 _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 156 8 CoreFoundation 0x3244f4bc CFRunLoopRunSpecific + 2192 9 CoreFoundation 0x3244ec18 CFRunLoopRunInMode + 44 10 GraphicsServices 0x342e91c0 GSEventRunModal + 188 11 UIKit 0x331b5c28 -[UIApplication _run] + 552 12 UIKit 0x331b4228 UIApplicationMain + 960 13 SimpleWeight 0x00002c3a main (main.m:14) 14 SimpleWeight 0x00002c04 0x1000 + 7172
スタックトレースのメソッド名と行番号が解決されているのがわかります。
今回もこれでどこでクラッシュしたのかが特定でき、問題を解決することができました。
この方法で、Ad Hocビルドでテスターの方にテストしてもらったり、iTunes Connectに寄せられたクラッシュログを解析して、問題の修正に役立てることができます。特に、リリース後にユーザーの方から原因不明で「落ちる」と報告されたり、レビューに書かれたりして再現ができない時などには、クラッシュログが入手できると非常に有用です。





