[1999/06/10] vcdc plus 1999 jun / visual c++ 6.0 デバッグ テクニック
Post on 14-Jul-2015
84 Views
Preview:
TRANSCRIPT
Visual C++ 6.0
デバッグ
テクニック
Developer Product Marketing
Visual C++ Product Manager
Tatsuhiko Tanaka
Microsoft,KK
注意:アンドキュメント情報について
Visual C++ 6.0のみで有効
文書化されていない
テストされていない
テクニカルサポートなし
次バージョンに組み込まれるとは限らない
正常に動作する保証なし
ステップイン回避
特定のコードへのステップインを回避
例えば、コンストラクタやオペレータ、必要のないモジュールなどへのステップインを回避可能
autoexp.datを編集
[ExecutionControl]セクションを追加
次のような行を追加
functionname=NoStepInto
アンドキュメント情報
ステップイン回避
MFCでの例[ExecutionControl]
CString::CString=NoStepInto
CString::operator==NoStepInto
関数名で指定
ユーザ関数も指定可能
統合開発環境の起動時に情報を読み込む
アンドキュメント情報
システムへのブレークポイント
Windows NTのみ(Windows 9xでは禁じられている)
DLLを特定する
lib¥win32api.csv の中からブレークポイントを設定するAPIが含まれるDLLを探す
完全な名前を特定する
デバッグ情報なし:dumpbin /exports name.dll | findstr CreateFile (オプションの変更が必要)
デバッグ情報あり:dumpbin /symbols name.dbg | findstr CreateFile
システムへのブレークポイント
ブレークポイントを {,,dllname} function に設定する
例: デバッグ情報なし デバッグ情報あり
{,,kernel32.dll} CreateFileA _CreateFileA@28
{,,user32.dll} MessageBoxA _MessageBoxA@16
引数の値によってブレークさせる場合
ブレークポイントを上記のように設定する
引数の位置によるスタックのオフセットを計算する
ブレークの条件を以下のように設定する
例: dw esp + 0x8 == 0xffffffff
データ ブレークポイント
一般的な例1:0x12345678が変更されたときに停止する場合
*(long *)0x12345678, length = 1
一般的な例2:m_memberが変更されたときに停止する場合
コードのエミュレーションを行うので、遅くなる
遅くならないためには、m_menberのアドレスを取得して使用する
*(long *)<m_memberのアドレス>
カウント ブレークポイント
もし15回目のコールで問題が発生する場合、ブレークポイントのスキップカウントを 15 - 1 に設定する
もし回数がわからない場合は、以下の方法で回数を特定する
スキップカウントに大きな数値を入れる
例:10000 (C)
アプリケーションを問題が発生するまで実行する
スキップカウントの残数を控える (X)
スキップカウントに C - X - 1 を入れて再実行する
タイミングコード
擬似レジスタ@clk
ウオッチウィンドウに @clk を追加し、ゼロに初期化する
ステップするごとに掛かった時間をナノセコンド単位で表示する
アセンブラレベルのステップでは正確ではない
デバッガ自体のオーバーヘッドがあるため
アンドキュメント情報
エディット・コンティニュー
デバッグ中にソースの修正が可能
リビルド、リスタートの必要なし
デバッグ時間の大幅な短縮
/ZI コンパイラスイッチにより使用可能
デフォルトでオン
デバッグ命令を実行したときに自動的に起動
実行、ステップインなどの命令で起動する
オプションで自動起動をオフにできる
エディット・コンティニュー
エディット・コンティニュー診断メッセージ
エディット・コンティニューの際に表示される情報のレベルをレジストリによって変更可能
以下のレジストリを変更HKEY_CURRENT_USER¥Software¥Microsoft¥DevStudio¥6.0¥Debug¥ENCTraceLevel
レベル 診断情報
0 フィードバックなし
1 メッセージ、エラー
2 メッセージ、エラー、警告 (デフォルト)
3 トレース情報、メッセージ、エラー、警告
エディット・コンティニュー
テクニック
Alt + F10 で実行中のアプリケーションに適用
アプリケーションのブレークを行う必要なし
外部プロジェクトのコードの変更
外部のプロジェクトに対して、プロジェクトを読み込まなくてもエディット・コンティニューを適用可能
[次に実行するステートメント]の併用
EIPを変更させることにより、通過してしまったコードを再検証可能
エディット・コンティニュー
エディットコンティニューの制限
リソースファイルの変更
読取専用ファイルの変更
最適化されたソースコードの変更
例外処理ブロックの変更
新しいデータ型の追加、またはデータ型の変更
関数の削除、または関数プロトタイプの変更
グローバルまたはスタティックコードの変更
50ファイル以上のコンパイルが必要となる場合
新しいソースファイルの追加 など
マルチスレッドデバッグ
スレッド名の設定と表示
後述のSetThreadName()を使用することにより、スレッドに名前を付けることが可能
名前は最大9文字まで
名前はスレッドダイアログに表示される
アンドキュメント情報
マルチスレッドデバッグSetThreadName
Usage:
SetThreadName(DWORD ThreadID, const char *szName, DWORD dwReserved);
dwReservedにはゼロを設定する
任意のスレッドに設定可能
最後の設定した名前が有効になる
アンドキュメント情報
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name
DWORD dwThreadID; // thread ID
DWORD dwFlags; // reserved for future use, must be zero
}THREADNAME_INFO;
void SetThreadName(DWORD dwThread, LPCSTR szThreadName, DWORD dwFlags)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = szThreadName;
info.dwThreadID = dwThread;
info.dwFlags = dwFlags;
__try
{
RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info);
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
}
}
マルチスレッドデバッグSetThreadName.cpp アンドキュメント情
報
モジュール一覧
[デバッグ|モジュール]でダイアログ表示
現在の実行中のモジュールを表示する
Orderをクリックすることにより、読み込まれた順に表示可能 (デフォルト)
クラッシュ時のアドレスから、モジュールを特定可能
どのDLLでクラッシュしているかを容易に知ることができる
ウオッチ変数の書式指定記号
ウオッチウィンドウでカンマのあとに指定記号 形式 例
d 符号付10進整数 1234
s 文字列 "Hello world"
su Unicode文字列 "Hello world"
hr HRESULTまたは S_OK
Win32エラーコード
wc ウィンドウクラスフラグ WC_DEFAULTCHAR
wm Windowsメッセージ番号 WM_CLOSE
エラー情報の取得
擬似レジスタ@err
現在のスレッドの最新エラーコードを表示
ウオッチウィンドウで使用可能
GetLastError関数が返す値と同じ
修飾子 hr を指定することによりエラーメッセージを表示
リリースビルドで動かない場合(デバッグビルドでは動作する)
/GZ オプションを使用
ローカル変数の自動初期化 (0xCC の書き込み)
関数ポインタコールスタックの正当性チェック
コールスタックの正当性チェック
top related