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