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です.(転者注)
簡単な例:

#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ファイルを使用してプログラムクラッシュの原因を見つけることができます.