2013-12-22 5 views
0

다음 코드의 경우 왜 ERROR_INVALID_HANDLE 오류가 발생합니까? 내가 도대체 ​​뭘 잘못하고있는 겁니까?Windows에서 호출 스택을 가져올 수 없습니다.

#include <Windows.h> 
#include <DbgHelp.h> 

#include <cstddef> 
#include <cstring> 
#include <iostream> 

void print_call_stack() 
{ 
    HANDLE cur_process_handle = GetCurrentProcess(); 
    HANDLE cur_thread_handle = GetCurrentThread(); 

    CONTEXT cur_thread_context; 
    std::memset(&cur_thread_context, 0, sizeof(CONTEXT)); 
    cur_thread_context.ContextFlags = CONTEXT_FULL; 
    if (!GetThreadContext(cur_thread_handle, &cur_thread_context)) 
    { 
    std::cerr << "An error occurred while using function GetThreadContext. " 
     << "Error code: " << GetLastError() << '\n'; 
    return; 
    } 

    STACKFRAME64 sf; 
    std::memset(&sf, 0, sizeof(sf)); 
    sf.AddrPC.Mode   = AddrModeFlat; 
    sf.AddrStack.Mode  = AddrModeFlat; 
    sf.AddrFrame.Mode  = AddrModeFlat; 
#ifdef _M_IX86 // Intel Only! 
    sf.AddrPC.Offset  = cur_thread_context.Eip; 
    sf.AddrStack.Offset = cur_thread_context.Esp; 
    sf.AddrFrame.Offset = cur_thread_context.Ebp; 
#endif 
#ifdef _M_X64 // Intel Only! 
    sf.AddrPC.Offset  = cur_thread_context.Rip; 
    sf.AddrStack.Offset = cur_thread_context.Rsp; 
    sf.AddrFrame.Offset = cur_thread_context.Rbp; 
#endif 
#ifdef _M_IA64 // Itanium 
#pragma message("fix me") 
    sf.AddrPC.Offset  = 0; 
    sf.AddrStack.Offset = 0; 
    sf.AddrFrame.Offset = 0; 
#endif 

#ifdef _M_IX86 
    DWORD machine_type = IMAGE_FILE_MACHINE_I386; 
#endif 
#ifdef _M_X64 
    DWORD machine_type = IMAGE_FILE_MACHINE_AMD64; 
#endif 
#ifdef _M_IA64 
    DWORD machine_type = IMAGE_FILE_MACHINE_IA64; 
#endif 

    int count = 0; 
    // According to MSDN, the sum of FramesToSkip and FramesToCapture 
    // must be less than 63 in case of Windows Server 2003 and Windows XP, 
    // so set it to 62 
    void* trace[62]; 

    while (StackWalk64(
    machine_type 
    , cur_process_handle 
    , cur_thread_handle 
    , &sf 
    , &cur_thread_context 
    , NULL 
    , SymFunctionTableAccess64 
    , SymGetModuleBase64 
    , NULL 
    ) == TRUE && count < sizeof(trace)/sizeof(*trace)) 
    { 
    trace[count++] = reinterpret_cast<void*>(sf.AddrPC.Offset); 
    } 

    for (std::size_t i = 0; i < count; ++i) 
    { 
    const int kMaxNameLength = 256; 
    DWORD_PTR frame = reinterpret_cast<DWORD_PTR>(trace[i]); 

    ULONG64 buffer[ 
     (sizeof(SYMBOL_INFO) + 
     kMaxNameLength * sizeof(wchar_t) + 
     sizeof(ULONG64) - 1)/
     sizeof(ULONG64)]; 
     std::memset(buffer, 0, sizeof(buffer)); 

     // Initialize symbol information retrieval structures. 
     DWORD64 sym_displacement = 0; 
     PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(&buffer[0]); 
     symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 
     symbol->MaxNameLen = kMaxNameLength - 1; 
     BOOL has_symbol = SymFromAddr(
     cur_process_handle 
     , frame 
     , &sym_displacement 
     , symbol 
    ); 
     if (has_symbol == FALSE) 
     { 
     std::cerr << "An error occurred while using function SymFromAddr." 
        << " Error code: " << GetLastError() << '\n'; 
     } 

     // Attempt to retrieve line number information. 
     DWORD line_displacement = 0; 
     IMAGEHLP_LINE64 line = {}; 
     line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 
     BOOL has_line = SymGetLineFromAddr64(
     cur_process_handle 
     , frame 
     , &line_displacement 
     , &line 
    ); 
     if (has_line == FALSE) 
     { 
     std::cerr << "An error occurred while using function SymGetLineFromAddr64." 
        << " Error code: " << GetLastError() << '\n'; 
     } 

     if (has_symbol == TRUE) 
     { 
     std::cout << symbol->Name << " [0x" << trace[i] << "+" 
      << sym_displacement << "]"; 
     } 
     else 
     { 
     std::cout << "(No symbol) [0x" << trace[i] << "]"; 
     } 

     if (has_line == TRUE) 
     { 
     std::cout << " (" << line.FileName << ":" << line.LineNumber << ")"; 
     } 

     std::cout << '\n'; 
    } 
} 

int main() 
{ 
    print_call_stack(); 
} 
+1

코드의 어느 줄에 오류가 있습니까? –

+0

@Mats Petersson SymFromAddr 및 SymGetLineFromAddr64 함수 사용의 경우 이러한 오류가 발생했습니다. – FrozenHeart

+0

그리고 확실히 심볼이 있습니까? –

답변

관련 문제