VS 2005(vs 2008,vs 2010)mapファイルを使用してプログラムがクラッシュした原因を検索
VS 2005 mapファイルを使用したシーケンサのクラッシュ原因
一般的なプログラムのクラッシュはdebugを通じて(通って)ことができて、プログラムを探し当ててその1行のコードでクラッシュして、最近1つのマルチスレッドのプログラムを編んで、すべてそこで間違いが発生することを知らないで、マルチスレッドは同時で、また単行のデバッグがよくなくて、ついに1つの比較的に良い方法を見つけて原因を探して、mapファイルを生成することを通じて(通って)、2005 mapファイルを取り消して行番号の情報を生成(vc 6.0では行番号情報を生成することができ、microsoftがどのように考えているのか分からず、2005でキャンセルされた)は、その関数にのみ位置決めされてクラッシュする.ここではcodファイル、すなわちマシンコードというファイルを生成することで、その行に具体的に位置決めすることができる.
まずvc 2005を構成してmapファイルとcodファイルを生成します.
(1).mapファイル:property->Configuration Properties->Linker->DebuggingのGenerate Map File選択Yes(/MAP);
(2)-codファイル:property->Configuration Properties->C/C+->output FilesでAssembler OutPutでAssembly,Maching Code and Source(/FAcs)を選択し、マシン、ソースコードを生成します.
上記のpropertyは、「ツール」メニューのpropertyではなく、「プロジェクト」メニューのpropertyです.(転者注)
簡単な例:
C++コード #include "stdafx.h" void errorFun(int * p) { *p=1; } int _tmain(int argc, _TCHAR* argv[]) { int * p=NULL; errorFun(p); return 0; }
errorFunでは、*p=1という行でエラーが発生しました.pに申請スペースがないため、実行時にエラーが発生し、ポップアップしました.
Unhandled exception at 0x004113b1 in testError.exe: 0xC0000005: Access violation writing location 0x00000000.
0 x 004113 b 1でプログラムがクラッシュしました.
具体的な手順:
(1)debugファイルの下でmapファイルを開き、クラッシュ関数を位置決め.
mapファイルの先頭にはいくつかのリンク情報があり、関数と実始アドレス情報を探します.アドレスは関数の開始アドレスです.
Address Publics by Value Rva+Base Lib:Object
0000:00000000 ___safe_se_handler_count 00000000
0000:00000000 ___safe_se_handler_table 00000000
0000:00000000 ___ImageBase 00400000
0001:00000000 __enc$textbss$begin 00401000
0001:00010000 __enc$textbss$end 00411000
0002:00000390
?errorFun@@YAXPAH@Z 00411390 f testError.obj
0002:000003d0 _wmain
004113d0 f testError.obj
0002:00000430 __RTC_InitBase 00411430 f MSVCRTD:init.obj
0002:00000470 __RTC_Shutdown 00411470 f MSVCRTD:init.obj
0002:00000490 __RTC_CheckEsp 00411490 f MSVCRTD:stack.obj
0002:000004c0 @_RTC_CheckStackVars@8 004114c0 f MSVCRTD:stack.obj
0002:00000540 @_RTC_AllocaHelper@12 00411540 f MSVCRTD:stack.obj
....
プログラムクラッシュアドレス0 x 004113 b 1は、このアドレスよりも大きい最初の004113 d 0を見つけ、前のアドレスは00411390であり、アドレスは関数の開始アドレスであるため、クラッシュが発生した関数はerrorFunであり、この関数の初期アドレスは00411390である.
(2)具体的なクラッシュ行番号を探し出す.
(2)から分かるように、エラー発生関数はerrorFunである、testError.objでtestError.codファイルを開き、errorFun関数が生成するマシンコードを見つける.
?errorFun@@YAXPAH@Z PROC ; errorFun, COMDAT
; 7 : {
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 81 ec c0 00 00
00 sub esp, 192 ; 000000c0H
00009 53 push ebx
0000a 56 push esi
0000b 57 push edi
0000c 8d bd 40 ff ff
ff lea edi, DWORD PTR [ebp-192]
00012 b9 30 00 00 00 mov ecx, 48 ; 00000030H
00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
0001c f3 ab rep stosd
; 8 : *p=1;
0001e 8b 45 08 mov eax, DWORD PTR _p$[ebp]
00021 c7 00 01 00 00
00 mov DWORD PTR [eax], 1
; 9 : }
00027 5f pop edi
00028 5e pop esi
00029 5b pop ebx
0002a 8b e5 mov esp, ebp
0002c 5d pop ebp
0002d c3 ret 0
(説明:7,8,9はソースコードを表す行番号です.
00000 55 push ebp,00000は相対オフセットであり,55はマシンコード番号,push ebp,00000は符号化である.
(2)相対オフセットアドレス、すなわち、クラッシュアドレス−関数開始アドレスを算出することにより、0 x 041133 b 1−0 x 00411390=0 x 21(16進数のカウント)とする.0 x 21の行に対応するマシンコードは、00021 c 7 00 01 00であり、上を見ると8行目*p=1である.生成された符号化は、この行のプログラムがクラッシュしたことがわかる.
終了語:もちろんこれは簡単な例ですが、実際に実行するとこの行のエラーであることがわかりますが、大きなプロジェクト、特にマルチスレッドが同時発生している場合、その行のエラーを見つけるのは難しいので、mapとcodファイルを使用してプログラムクラッシュの原因を見つけることができます.
一般的なプログラムのクラッシュはdebugを通じて(通って)ことができて、プログラムを探し当ててその1行のコードでクラッシュして、最近1つのマルチスレッドのプログラムを編んで、すべてそこで間違いが発生することを知らないで、マルチスレッドは同時で、また単行のデバッグがよくなくて、ついに1つの比較的に良い方法を見つけて原因を探して、mapファイルを生成することを通じて(通って)、2005 mapファイルを取り消して行番号の情報を生成(vc 6.0では行番号情報を生成することができ、microsoftがどのように考えているのか分からず、2005でキャンセルされた)は、その関数にのみ位置決めされてクラッシュする.ここではcodファイル、すなわちマシンコードというファイルを生成することで、その行に具体的に位置決めすることができる.
まずvc 2005を構成してmapファイルとcodファイルを生成します.
(1).mapファイル:property->Configuration Properties->Linker->DebuggingのGenerate Map File選択Yes(/MAP);
(2)-codファイル:property->Configuration Properties->C/C+->output FilesでAssembler OutPutでAssembly,Maching Code and Source(/FAcs)を選択し、マシン、ソースコードを生成します.
上記のpropertyは、「ツール」メニューのpropertyではなく、「プロジェクト」メニューのpropertyです.(転者注)
簡単な例:
C++コード
#include "stdafx.h"
void errorFun(int * p)
{
*p=1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int * p=NULL;
errorFun(p);
return 0;
}
errorFunでは、*p=1という行でエラーが発生しました.pに申請スペースがないため、実行時にエラーが発生し、ポップアップしました.
Unhandled exception at 0x004113b1 in testError.exe: 0xC0000005: Access violation writing location 0x00000000.
0 x 004113 b 1でプログラムがクラッシュしました.
具体的な手順:
(1)debugファイルの下でmapファイルを開き、クラッシュ関数を位置決め.
mapファイルの先頭にはいくつかのリンク情報があり、関数と実始アドレス情報を探します.アドレスは関数の開始アドレスです.
Address Publics by Value Rva+Base Lib:Object
0000:00000000 ___safe_se_handler_count 00000000
0000:00000000 ___safe_se_handler_table 00000000
0000:00000000 ___ImageBase 00400000
0001:00000000 __enc$textbss$begin 00401000
0001:00010000 __enc$textbss$end 00411000
0002:00000390
?errorFun@@YAXPAH@Z 00411390 f testError.obj
0002:000003d0 _wmain
004113d0 f testError.obj
0002:00000430 __RTC_InitBase 00411430 f MSVCRTD:init.obj
0002:00000470 __RTC_Shutdown 00411470 f MSVCRTD:init.obj
0002:00000490 __RTC_CheckEsp 00411490 f MSVCRTD:stack.obj
0002:000004c0 @_RTC_CheckStackVars@8 004114c0 f MSVCRTD:stack.obj
0002:00000540 @_RTC_AllocaHelper@12 00411540 f MSVCRTD:stack.obj
....
プログラムクラッシュアドレス0 x 004113 b 1は、このアドレスよりも大きい最初の004113 d 0を見つけ、前のアドレスは00411390であり、アドレスは関数の開始アドレスであるため、クラッシュが発生した関数はerrorFunであり、この関数の初期アドレスは00411390である.
(2)具体的なクラッシュ行番号を探し出す.
(2)から分かるように、エラー発生関数はerrorFunである、testError.objでtestError.codファイルを開き、errorFun関数が生成するマシンコードを見つける.
?errorFun@@YAXPAH@Z PROC ; errorFun, COMDAT
; 7 : {
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 81 ec c0 00 00
00 sub esp, 192 ; 000000c0H
00009 53 push ebx
0000a 56 push esi
0000b 57 push edi
0000c 8d bd 40 ff ff
ff lea edi, DWORD PTR [ebp-192]
00012 b9 30 00 00 00 mov ecx, 48 ; 00000030H
00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
0001c f3 ab rep stosd
; 8 : *p=1;
0001e 8b 45 08 mov eax, DWORD PTR _p$[ebp]
00021 c7 00 01 00 00
00 mov DWORD PTR [eax], 1
; 9 : }
00027 5f pop edi
00028 5e pop esi
00029 5b pop ebx
0002a 8b e5 mov esp, ebp
0002c 5d pop ebp
0002d c3 ret 0
(説明:7,8,9はソースコードを表す行番号です.
00000 55 push ebp,00000は相対オフセットであり,55はマシンコード番号,push ebp,00000は符号化である.
(2)相対オフセットアドレス、すなわち、クラッシュアドレス−関数開始アドレスを算出することにより、0 x 041133 b 1−0 x 00411390=0 x 21(16進数のカウント)とする.0 x 21の行に対応するマシンコードは、00021 c 7 00 01 00であり、上を見ると8行目*p=1である.生成された符号化は、この行のプログラムがクラッシュしたことがわかる.
終了語:もちろんこれは簡単な例ですが、実際に実行するとこの行のエラーであることがわかりますが、大きなプロジェクト、特にマルチスレッドが同時発生している場合、その行のエラーを見つけるのは難しいので、mapとcodファイルを使用してプログラムクラッシュの原因を見つけることができます.