2011-12-04 7 views
0

あるプロセスのスレッドの呼び出しスタックを取得しようとすると、確かにより多くの(少なくとも5つのフレームがありますが)常に同じ単一のフレームを取得します。StackWalk64()は単一のフレームを返します

StackWalk64()は常に最初の呼び出しに成功した - とフレームを返す:

AddrPC.Offset = 18446744072850558156 

しかし、すぐに呼び出すことがエラーID 998-ERROR_NOACCESSで失敗第二に(それは、このエラーではないことかもしれませんこの呼び出しのために、MSDNが言うように)。

さらに、このアドレスをSymFromAddr()でシンボル名に解決しようとすると、エラー126-ERROR_MOD_NOT_FOUND(SymInitialize(m_processHandler、NULL、TRUE)の呼び出しが成功した後)で失敗します。ここで

はコードです:

#ifdef _M_IX86 
    // 
    // Disable global optimization and ignore /GS waning caused by 
    // inline assembly. 
    // 
    #pragma optimize("g", off) 
    #pragma warning(push) 
    #pragma warning(disable : 4748) 
#endif 

bool EchoProfiler::getThreadStackTrace(__in HANDLE h_thread, __out vector<DWORD64> &framesVec) 
{ 
CONTEXT threadContext; 
if (GetThreadContext(h_thread, &threadContext) == 0) 
{ 
    cout << "Error: GetThreadContext() failed with error ID " << GetLastError() << endl; 
    return false; 
} 

//initialize stack frame 
DWORD MachineType; 
STACKFRAME64 StackFrame; 
ZeroMemory(&StackFrame, sizeof(STACKFRAME64)); 

MachineType     = IMAGE_FILE_MACHINE_I386; 
StackFrame.AddrPC.Offset = threadContext.Eip; 
StackFrame.AddrPC.Mode  = AddrModeFlat; 
StackFrame.AddrFrame.Offset = threadContext.Ebp; 
StackFrame.AddrFrame.Mode = AddrModeFlat; 
StackFrame.AddrStack.Offset = threadContext.Esp; 
StackFrame.AddrStack.Mode = AddrModeFlat; 

PVOID contextRec = (MachineType == IMAGE_FILE_MACHINE_I386) ? NULL : &threadContext; 
int i=0; 
// enumerate all the frames in the stack 
for (i=1 ; ; i++) 
{ 
    if (StackWalk64(MachineType, targetProcessHandler, h_thread, &StackFrame, 
     contextRec, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL) == false) 
    { 
     // in case it failed or we have finished walking the stack. 
     cout << "Error: StackWalk64() failed with error ID " << GetLastError() << endl; 
     i--; 
     break; 
     // return false; 
    } 

    if (StackFrame.AddrPC.Offset != 0) 
    { 
     // Valid frame. 
     cout << "Frame #" << i << " address - " << StackFrame.AddrPC.Offset << endl; 
     framesVec.push_back(StackFrame.AddrPC.Offset); 
    } 
    else 
    { 
     // Base reached. 
     break; 
    } 
} 

//cout << "StackWalk64 found " << i << " stack frames:" << endl; 
//i = 1; 
//for (FramesConstItr itr=framesVec.begin() ; itr != framesVec.end() ; itr++ , i++) 
// cout << i << " - " << *itr << endl; 

return true; 
} 

#ifdef _M_IX86 
    #pragma warning(pop) 
    #pragma optimize("g", on) 
#endif 

それは何だろうか?

+0

targetProcessHandlerとどのようにそれが初期化されているどのようなものです: 次のように解決私の問題を追加しますか? –

+0

'HANDLE targetProcessHandler = OpenProcess(PROCESS_ALL_ACCESS、false、pId)を使って初期化 ' –

答えて

1

解決策:

私は文脈構造が正しく初期化されなければならないと言いました。

memset(&threadContext, 0, sizeof(CONTEXT)); 
threadContext.ContextFlags = CONTEXT_FULL; 

おかげ

+0

なぜ最適化を無効にしますか?あなたは絶対にそうしているようですが、それはなぜ必要なのでしょうか?私は私のアプリで最適化を無効にしない場合は、スタックが不正確になる。スタックプリンタアプリケーションの出力には、関数アドレスが少なくなっています。何が原因なのか考えていますか? –

関連する問題