ソフトウェアを開発し続けて早六年。 バグを憎んで人を憎まず。。 株式投資で脱サラをめざすITエンジニアのホームページ......
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
WindowsのC++でコールスタック(関数呼び出しの階層状態,Java風に言うとスタックトレース)を取得する方法です。
例外やエラー時にコールスタックをロギングすると
デバッグがとても楽になります。

私の昔のサイトでも同じようなのを載せてたんですけど、
とても重要な機能なので、こっちにも買いときます。

※WindowsXP SP2では、なぜかうまく取れませんでした。
※どなたか解決方法をご存知でしたら、おしえてください。

001 #pragma comment(lib, "imagehlp.lib")
002 #include <windows.h>
003 #include <imagehlp.h>
004 #include <vector>
005 #include <string>
006
007
008 static size_t ConvertAddress(HANDLE hProcess,DWORD dwAddr,char *szOutBuf);
009
010 ///コールスタックを取得する
011 void GetStackTrace(std::string &str){
012 static bool _bSymIsInit = false;
013 HANDLE hProcess = ::GetCurrentProcess();
014
015
016 if(!_bSymIsInit){
017 DWORD dwOpts = ::SymGetOptions();
018 ::SymSetOptions(dwOpts | SYMOPT_LOAD_LINES);
019
020 if(!::SymInitialize(hProcess,NULL,FALSE)){
021 //TODO
022 //DEBUG_WRITELN("::SymInitialize FAILED");
023 _bSymIsInit = false;
024 }else{
025 _bSymIsInit = true;
026 }
027 }
028
029 CONTEXT ctx;
030 ctx.ContextFlags = CONTEXT_FULL;
031 std::vector<DWORD> vAddrs;
032
033 if(::GetThreadContext(::GetCurrentThread(),&ctx)){
034 STACKFRAME frame;
035 DWORD dwMachine;
036 memset(&frame,0,sizeof(STACKFRAME));
037 frame.AddrPC.Mode = AddrModeFlat;
038
039 dwMachine = IMAGE_FILE_MACHINE_I386;
040 frame.AddrPC.Offset = ctx.Eip;
041 frame.AddrStack.Offset = ctx.Esp;
042 frame.AddrFrame.Offset = ctx.Ebp;
043 frame.AddrStack.Mode = AddrModeFlat;
044 frame.AddrFrame.Mode = AddrModeFlat;
045
046 for(DWORD dw = 0;dw < 512;dw++){
047 if(!::StackWalk(dwMachine,
048 hProcess,
049 hProcess,
050 &frame,
051 &ctx,
052 NULL,
053 SymFunctionTableAccess,//FunctionTableAccessRoutine
054 SymGetModuleBase,//GetModuleBaseRoutine
055 NULL//TranslateAddress
056 )){
057 break;
058 }
059 if(0 != frame.AddrPC.Offset){
060 vAddrs.push_back(frame.AddrPC.Offset);
061 }
062 }
063 }//if(::GetThreadContext(::GetCurrentThread(),&ctx)){
064
065 size_t dwSymSize = 0;
066 char szSym[MAX_PATH * 2];
067 std::vector<DWORD>::iterator itr;
068
069 for(itr = vAddrs.begin();itr != vAddrs.end();itr++){
070 dwSymSize = ConvertAddress(hProcess,*itr,szSym);
071 str += szSym;
072 }
073 }
074 static size_t ConvertAddress(HANDLE hProcess,DWORD dwAddr,char *szOutBuf){
075 char szTmp[MAX_PATH + sizeof(IMAGEHLP_SYMBOL)];
076
077 PIMAGEHLP_SYMBOL pIHS = (PIMAGEHLP_SYMBOL)&szTmp;
078 IMAGEHLP_MODULE stIHM;
079 char * pCurPos = szOutBuf;
080
081 memset(pIHS,0,MAX_PATH + sizeof(IMAGEHLP_SYMBOL));
082 memset(&stIHM,0,sizeof(IMAGEHLP_MODULE));
083
084 pIHS->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
085 pIHS->Address = dwAddr;
086 pIHS->MaxNameLength = MAX_PATH;
087
088 stIHM.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
089
090 pCurPos += sprintf(pCurPos,"0x%08X ",dwAddr);
091
092 if(::SymGetModuleInfo(hProcess,dwAddr,&stIHM)){
093 char *szName = strrchr(stIHM.ImageName,'\\');
094 if(szName){
095 szName++;
096 }else{
097 szName = stIHM.ImageName;
098 }
099 pCurPos += sprintf(pCurPos,"%s: ",szName);
100 }else{
101 pCurPos += sprintf(pCurPos,"<Unknown Module>: ");
102 }
103 DWORD dwDisp;
104 if(::SymGetSymFromAddr(hProcess,dwAddr,&dwDisp,pIHS)){
105 if(0 == dwDisp){
106 pCurPos += sprintf(pCurPos,"%s",pIHS->Name);
107 }else{
108 pCurPos += sprintf(pCurPos,
109 "%s + %d bytes",
110 pIHS->Name,
111 dwDisp);
112 }
113 IMAGEHLP_LINE stIHL;
114 memset(&stIHL,0,sizeof(IMAGEHLP_LINE));
115 stIHL.SizeOfStruct = sizeof(IMAGEHLP_LINE);
116
117 if(::SymGetLineFromAddr(hProcess,dwAddr,&dwDisp,&stIHL)){
118 pCurPos += sprintf(pCurPos,
119 "\n\t\t%s, Line %d",
120 stIHL.FileName,
121 stIHL.LineNumber);
122 if(0 != dwDisp){
123 pCurPos += sprintf(pCurPos,
124 " + %d bytes",
125 dwDisp);
126 }
127 }
128 }else{
129 pCurPos += sprintf(pCurPos,"<Unknown Symbol>");
130 }//if(::SymGetSymFromAddr(hProcess,dwAddr,&dwDisp,pIHS)){
131
132 pCurPos += sprintf(pCurPos,"\n");
133
134 return (pCurPos - szOutBuf);
135 }

スポンサーサイト

テーマ:プログラミング - ジャンル:コンピュータ


管理者にだけ表示を許可する
http://qnd.blog36.fc2.com/tb.php/8-0abaced1
この記事にトラックバックする(FC2ブログユーザー)
// HOME // 
シャトー・フルール・ド・ジャン・ゲイ・レゼルヴ 2001
↑これ、お気に入りのワインです
毎日ペースで飲んでる中からの
厳選(?)チョイスする予定。。
(ちなみに赤が好き)
カテゴリー
最近の記事
最近のコメント
最近のトラックバック
月別アーカイブ
ブロとも申請フォーム
ブログ内検索

RSSフィード
リンク
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。