Apple iPhone 3GとiPhone SDKを使ってアプリケーションをデバッグするための情報。
更新:11/10/02 | iPhone SDKでデバッグ| iPhone SDK Tech
デバッグとは
言わずもがな、不覚にもアプリケーションが正しく動かなかった場合に原因を突き止めて修正する作業のことです。
NSLogの利用
NSLogを利用してタイムスタンプや変数の内容等をデバッグウィンドウに表示することで、原因を特定できることが多々あります。例えばNilであるはずがないオブジェクトが存在していることを突き止めれば、これをインスタンス化したり代入している箇所に問題があると言えます。
ただ、NSLogをDevice用のアプリケーションに入れておくとログが物理的に生成されてしまうため、スイッチを付けて判定させると便利です。
#if kShouldPrintLog
NSLog(@"*** init_bydate_statement defined");
#endif
こんな感じです。kShouldPrintLogを1にしている場合だけログが出力されます。問題点は 、ソースコードが大変見通し悪くなる点です。
ブレークポイント
コマンド+\や、コードウィンドウの左側をクリックすることでブレークポイントを設定することが出来ます。プログラムは、指定した部分を通ると一時停止してカーソルを変数にあてると実際の値を見ることも出来ます。(Out of scopeで見えないこともあり、あまりあてにしてはいけません)
ブレークポイントはまとめて一時的に無効にしたり削除したりすることも出来ます。最近は、特定の箇所を通ったかどうか程度にしか使えない気がしています。変数の内容を表示したいのであればNSLogを使った方が確実で、クラッシュ箇所を特定したいのであれば次の方法を検討した方が確実です。
ツールバーの足跡
2010-01-17 18:11:34.959 App[25836:207] *** -[Record retain]: message sent to deallocated instance 0x452dd10
といったエラーが出て止まった際に、Xcodeのウィンドウからエラーに至るまでの足跡情報を表示させて、項目によっては該当するコードに移動することが出来ます。
上の場合、-[ほにゃらら]という部分を選択すると該当するコードに移動できる場合が多いです。
デバッグウィンドウからスタック情報を参照
予め、Xcodeの実行可能ファイルを選択して、次のオプションを追加しておきます。
MallocStackLogging
このオプションは、シミュレーターでしか使えないので注意が必要です。実行するプラットフォームを変える度にオプションを変更しなくてはならないので面倒ですが、次のコマンドを入力することでスタック情報を参照することが出来て、大変強力な情報を参照することが出来ます。
2010-01-17 18:24:51.741 App[26067:207] *** -[Record retain]: message sent to deallocated instance 0x4553480
(gdb)
(gdb) info malloc-history 0x4553480
Alloc: Block address: 0x04553480 length: 76
Stack - pthread: 0xa0a4b500 number of frames: 18
0: 0x98b008a3 in malloc_zone_calloc
1: 0x98b007fa in calloc
2: 0x9576d02f in _internal_class_createInstanceFromZone
3: 0x9576d1f7 in _internal_class_createInstance
4: 0x237f8fc in +[NSObject allocWithZone:] <----この辺りが怪しい
5: 0x237f7ea in +[NSObject alloc]
6: 0x4a04 in -[AppDelegate initializeRecord] at /Users/minoru/Documents/iPhoneSDK/App/Classes/AppDelegate.m:846
7: 0xad99 in -[RootViewController moveToAccountView] at /Users/name/Documents/iPhoneSDK/App/Classes/RootViewController.m:510
8: 0x3c0a9a in -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:]
9: 0x3bc8d8 in -[UITableView _userSelectRowAtIndexPath:]
10: 0x1a131ba in __NSFireDelayedPerform
11: 0x23c2ac0 in CFRunLoopRunSpecific
12: 0x23c1c48 in CFRunLoopRunInMode
13: 0x29ba78d in GSEventRunModal
14: 0x29ba852 in GSEventRun
15: 0x37e003 in UIApplicationMain
16: 0x2496 in main at /Users/name/Documents/iPhoneSDK/App/main.m:15
17: 0x2416 in start
(gdb)
EXC_BAD_ACCESSに有効なNSZombieEnabled
EXC_BAD_ACCESSは良く目にする不正終了メッセージの一つです。突然gdbにEXC_BAD_ACCESSが表示され終了しますが、前述のツールバーの足跡を追っても原因が釈然としないことが多いのが悩みの種です。
そこで、実行可能ファイルの実行時引数に次のオプションを追加します。
NSZombieEnabled:YES
すると、以下のように何が原因かを具体的に示してくれます。
以下の場合、Recordオブジェクトが既にdeallocされているにもかかわらずreleaseを投げていることが原因となっています。(それでもやっかいなのは、コード中で明示的にreleaseなんて投げていないという事実なのですが……)
2010-03-25 20:51:34.044 FreeJournal[1783:207] *** -[Record release]: message sent to deallocated instance 0x5519010
デバッグ要のユーザーログ出力
デバッグというとVB(というよりもMS-BASIC)などのインタプリタ寄りの言語やデバッグ方法に慣れている人は、ブレークポイントやステップ実行によるデバッグをしてしまいがちですが、オブジェクト指向、マルチスレッドプログラミングなどになるとこうした手法でのデバッグでは太刀打ちできません。
また、モバイルとはいえ一昔前のパソコン並みの性能を持っていますから少し大きめのプロジェクトになると一瞬で相当量の動きをするのでいちいち目で動きを追っていては日が暮れてしまいます。
そこで、定常的にユーザーログを標準出力に表示させる方法が分かり易いのでお勧めです。幾つかの方法がありますが、私が現在用いている方法は以下のコードを(基本的に)全てのメソッドの冒頭に挿入するという方法です。
#if kShouldPrintLog
NSLog(@"@%@ : [%s]", [self class], _cmd);
#endif
これによって、当該のメソッドが実行される際には1行クラス名、メソッド名が出力されるようになります。
メリット:コピー&ペーストで良いのでログ出力の実装が楽。
デメリット:引数が出力されない。
課題:3行必要。Xcode4ではビルド時にWarningとなる(!)
これによってバックトレースが取れない不正終了などでも、ログを見ればどのクラスのどのメソッドでとどめが刺されたかを大体突き止められます。
iPhoneローカルにログメッセージを出力する
複数のメンバー、テスターなどが存在していたり、実機を持ち歩いた状態ででテストを行いたい場合、前項のログを取得できず大変不便な自体となります。
レアな障害を捉えられたのにログもバックトレースも無しでは解析のしようもありません。そこで、標準出力の代わりにiPhoneのローカルにASCIIファイルとしてログを出力し、メールなどで送信できるようにする方法を紹介します。
UIは適当に実装してもらうとして、少なくとも1つのボタン(UIBUtton)を用意します。このボタンの役割は次の通りです。
・ログファイルを削除し、古いログデータをクリアする。
・ログの出力先をローカルファイルに切り替える。
- (BOOL)deleteLogFile {
[self finishLog];
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:[self loggingPath] error:nil]; [self startLog];
return success;
}
このように、ボタンが押されるとログファイルを閉じて、削除し、ログをファイルに出力開始するという仕組みです。
- (void)finishLog {
fflush(stderr);
dup2(dup(STDERR_FILENO), STDERR_FILENO); close(dup(STDERR_FILENO));
}
- (NSString*)loggingPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
return logPath;
}
- (void)startLog {
freopen([[self loggingPath] cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}
非常に簡便なコードなのですが、この手の紹介を見たことがありません。
因みに、メール送信画面に引き渡す場合は次のようにすればOKです。
- (void)sendLogByMail {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init]; picker.mailComposeDelegate = self;
[picker setSubject:[NSString stringWithFormat:@"%@ - Log", [self appName]]];
NSString *message = [NSString stringWithContentsOfFile:[self loggingPath] encoding:NSUTF8StringEncoding
error:nil];
[picker setMessageBody:message isHTML:NO];
[self.navigationController presentModalViewController:picker animated:YES]; [picker release];
}
[作成中]
- iPhone全般、一般
- iPhone OS 3.0ベータ版のレビュー
- iPhone OS 4.0ベータ版のレビュー
- iPhone SDKの開発環境、XCodeの基本
- iPhoneチュートリアル
- XCodeの便利なショートカット
- iPhone技術情報、開発テクニック
- iPhoneのSQLite3周りのテクニック
- iPhone SDKのトラブルシューティング
- iPhone SDKでGoogle Apps APIを利用する
- iPhone SDKを使ったデバッグ手法
- お勧めリンク
- ダウンロード
- ストリーミング関連
- Macintosh関連
-
- Macでも使えるDVDドライブ
- Leopard詳解
- iLife詳解
- Macの修復方法特集
- Apple MacBook (Pro)
- Macで無線LAN802.11n
- 新旧MacBookベンチマーク
- フルHD編集Apple iMovie&Final Cut Express
- ROXIO Toast Platinum
- フルHD編集Apple Final Cut X
- MacBookのHDD換装方法
- MacとWindowsのファイル共有
- MacでWindowsを遠隔操作
- WinユーザーのためのMac概論
- 無料の辞書検索ツール 英辞郎
- 代表的なタブブラウザの比較
- Macお勧めのフリーソフト紹介
- 無料のOffice環境 NeoOffice
- エミュレータ比較
- Macで最適バックアップ
- iGeek Indelible
- intego PersonalBackup
- EMC® Retrospect® for Mac
- Mac版 ウイルス対策
- Ruby On Rails インストール(Mac編)
- Ruby On Rails 開発の初歩(Model)
- Ruby On Rails 開発環境RadRails
- Ruby On Rails DBメンテナンス
- Excel, Wordを使ってMacで年賀状宛名印刷
- Windows関連
-
- EaseUS Todo Backupで完璧バックアップ
- DVD, Blu-rayリッピングツール AnyDVD HD
- キャプチャーソフト hunuaaCap
- Windows2003でリモートデスクトップ7を動かす
- 最適なバックアップソフトは
- robocopyによるバックアップ
- リージョンフリー
- リージョンフリー化を有効活用
- マルチブート
- Antivir®
- eTrust Antivirus
- AVG AntiVirus
- C#徹底講座
- メーラー Mailer
- VBA徹底活用術
- JustSystemメーラーShuriken
- FTPソフトとコマンドライン解説
- DOS/Vパーツリンク集
- Oracle10gBronze試験対策
- CDからMP3へ簡単に変換する方法
- メディアなど
- ハードウェア
-
- iPhone 3G
- iPhone 4
- iPod+iTunes
- iPhone SDK
- 色域(AdobeRGB)
- hp mini 1000
- 環境紹介
- KDDI au新旧プラン研究
- DVDをMP4にコンバート
- 無線LAN環境802.11n
- キャプチャボード
- HD-LANによるネットワークストレージ構築
- NEC LavieJ LJ500/5A
- LavieJ HDD換装
- LavieJ 調子の悪いHDDの復旧
- LavieJ 無線LANモジュールの換装
- LavieJ メモリの追加
- LavieJ バックアップ作成と復元
- Intel PRO/Wireless 2200BG
- 液晶・プラズマテレビ比較
- プリンタ(hp PSC2550)
- 万能リモコン クロッサム
- 婦人体温計 プチソフィア
- 婦人体温計 マドンナ
- ソフトウェア/サービス/開発SDK
- デジタル一眼レフカメラ
- テクニカル記事
- 趣味関連
- ゲーム 〜楽しいゲームの紹介や攻略法
- RoverMNI(ローバーミニ)
- 雑記
- その他
-
- ネットバンキングに便利な金融機関
- 便利なサイト翻訳機能
- 便利ツール GMail
- 無料電話Gizmoの嘘とほんと
- リンク:一般ページへのリンク集
- 相互リンク:相互リンク募集中!
- 本ページの統計:本サイトの統計データ公開
- コメント・フィードバック