VS 2005 mapファイルを使用してプログラムがクラッシュした原因を検索します(,いいです)
一般的なプログラムクラッシュはdebugを通じて、プログラムがその行のコードでクラッシュしたことを見つけることができて、最近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です.(転者注)
簡単な例:
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はソースコードを表す行番号です.
0000055 push ebp,00000は相対的にずれており,55はマシンコード番号,push ebp,00000は符号化されている.)
(2)相対オフセットアドレス,すなわちクラッシュアドレス−関数開始アドレス,0 x 004113 b 1−0 x 0041390=0 x 21(16進数のカウント)を計算する.0 x 21という行に対応するマシンコードを見つけたのは00021 c 7 00 01 00で、上を見ると8行目*p=1です.生成された符号化は,この行のプログラムがクラッシュしたことを示す.
終了語:もちろんこれは簡単な例ですが、実際に実行するとこの行のエラーであることがわかりますが、大きなプロジェクト、特にマルチスレッドが同時発生している場合、その行のエラーを見つけるのは難しいので、mapと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です.(転者注)
簡単な例:
#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はソースコードを表す行番号です.
0000055 push ebp,00000は相対的にずれており,55はマシンコード番号,push ebp,00000は符号化されている.)
(2)相対オフセットアドレス,すなわちクラッシュアドレス−関数開始アドレス,0 x 004113 b 1−0 x 0041390=0 x 21(16進数のカウント)を計算する.0 x 21という行に対応するマシンコードを見つけたのは00021 c 7 00 01 00で、上を見ると8行目*p=1です.生成された符号化は,この行のプログラムがクラッシュしたことを示す.
終了語:もちろんこれは簡単な例ですが、実際に実行するとこの行のエラーであることがわかりますが、大きなプロジェクト、特にマルチスレッドが同時発生している場合、その行のエラーを見つけるのは難しいので、mapとcodファイルを使用してプログラムクラッシュの原因を見つけることができます.