我正在嘗試爲多線程運行的進程獲取堆棧跟蹤,我能夠獲得主線程的堆棧跟蹤。但對於其他線程(屬於同一進程),即使我使用了正確的threadIds,我也爲所有線程(與主線程相同)獲取了相同的堆棧跟蹤。我確信那些線索不是正確的痕跡。如何獲得在進程中運行的所有線程的堆棧跟蹤?
以下是代碼,我不知道出了什麼問題。如果您有任何想法,請告訴我。謝謝..
我的pExPtrs爲空,我不會在異常時調用它。
void DoStackTraces (LPTSTR szString,DWORD dwSize, EXCEPTION_POINTERS *pExPtrs)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, static_cast<DWORD>(getpid()));
if (h != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
if(te.th32OwnerProcessID == static_cast<DWORD>(getpid())) {
std::cout << "Process 0x%04x | Thread 0x%04x\n"
<< te.th32OwnerProcessID << " | " << te.th32ThreadID
<< " Current ProcessID : " << getpid()
<< " dwSize : " << dwSize
<< " pExPtrs : " << pExPtrs
<< std::endl;
HANDLE hnd = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, te.th32ThreadID);
SuspendThread(hnd);
DoStackTraceThread(hnd,szString,dwSize,0);
ResumeThread(hnd);
std::cout << szString << std::endl;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
//HANDLE hThread = GetCurrentThread();
//DoStackTraceThread (hThread, szString,dwSize,pExPtrs);
}
void DoStackTraceThread (HANDLE hThread, LPTSTR szString ,
DWORD dwSize , EXCEPTION_POINTERS *pExPtrs)
{
if (g_bCsysDontGetProcessCritSec){return;}
sAutoLock al(g_stackTraceMux); // The code probably isn't thread safe.
if (g_cSym.isInstalled() == false) return;
HANDLE hProcess = GetCurrentProcess () ;
// If the symbol engine is not initialized, do it now.
if (FALSE == g_bSymIsInit)
{
DWORD dwOpts = APFSymGetOptions () ;
// Turn on load lines.
APFSymSetOptions (dwOpts |
SYMOPT_LOAD_LINES ) ;
if (FALSE == g_cSym.SymInitialize (hProcess ,
NULL ,
TRUE ))
{
std::cerr << "APF ERROR: DiagAssert : Unable to initialize the "
"symbol engine!!!" << std::endl;
}
else
{
g_bSymIsInit = TRUE ;
}
}
// The symbol engine is initialized so do the stack walk.
// The array of addresses.
ADDRVECTOR vAddrs ;
// The thread information.
CONTEXT stCtx ;
CONTEXT *pstCtx ;
GET_CURRENT_CONTEXT(stCtx, CONTEXT_FULL);
{
STACKFRAME64 stFrame ;
DWORD dwMachine ;
ZeroMemory (&stFrame , sizeof (STACKFRAME64)) ;
stFrame.AddrPC.Mode = AddrModeFlat ;
if (pExPtrs)
{
pstCtx=pExPtrs->ContextRecord;
}
else {
pstCtx=&stCtx;
}
dwMachine = IMAGE_FILE_MACHINE_I386 ;
if (pExPtrs){
stFrame.AddrPC.Offset = pstCtx->Eip ;
stFrame.AddrStack.Offset = pstCtx->Esp ;
stFrame.AddrFrame.Offset = pstCtx->Ebp ;
}
else {
stFrame.AddrPC.Offset = stCtx.Eip ;
stFrame.AddrStack.Offset = stCtx.Esp ;
stFrame.AddrFrame.Offset = stCtx.Ebp ;
}
stFrame.AddrStack.Mode = AddrModeFlat ;
stFrame.AddrFrame.Mode = AddrModeFlat ;
// Loop for the first 512 stack elements.
for (DWORD i = 0 ; i < 512 ; i++)
{
if (FALSE == StackWalkProc (dwMachine ,
hProcess ,
hThread ,
&stFrame ,
pstCtx ,
NULL ,
(PFUNCTION_TABLE_ACCESS_ROUTINE64)
APFSymFunctionTableAccess ,
GetModBase ,
NULL ))
{
break ;
}
// Also check that the address is not zero. Sometimes
// StackWalk returns TRUE with a frame of zero.
if (0 != stFrame.AddrPC.Offset)
{
vAddrs.push_back (stFrame.AddrPC.Offset) ;
}
}
// Now start converting the addresses.
DWORD64 dwSizeLeft = dwSize ;
DWORD64 dwSymSize ;
TCHAR szSym [ MAX_PATH * 2 ] ;
LPTSTR szCurrPos = szString ;
ADDRVECTOR::iterator loop ;
for (loop = vAddrs.begin () ;
loop != vAddrs.end () ;
loop++ )
{
dwSymSize = DoConvertAddress (*loop , szSym) ;
if (dwSizeLeft <= dwSymSize)
{
break ;
}
_tcscpy (szCurrPos , szSym) ;
szCurrPos += dwSymSize ;
dwSizeLeft -= dwSymSize ;
}
}
}
你應該提到你正在使用什麼編譯器,幷包含一個標籤。 – Donotalo 2012-02-28 11:16:33