c++ - 为什么 SymGetSymFromAddr64 不工作?它返回错误代码 126

标签 c++ winapi visual-c++ try-catch dbghelp

我正在尝试使用以下代码捕获有关异常的堆栈跟踪:

#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <Windows.h>
#include "dbghelp.h"

using namespace std;

#define TRACE_MAX_FUNCTION_NAME_LENGTH 1024

void function2()
{
    int a = 0;
    int b = 0;
    throw new exception;
}

void function1()
{
    int a = 0;
    function2();
}

void function0()
{
    function1();
}

LONG WINAPI FatalExceptionFilter(EXCEPTION_POINTERS* exception, DWORD exceptionCode)
{
    CONTEXT *context = exception->ContextRecord;
    HANDLE thread = GetCurrentThread();
    HANDLE process = GetCurrentProcess();
    STACKFRAME64 frame;
    DWORD image;
#ifdef _M_IX86
    image = IMAGE_FILE_MACHINE_I386;
    frame.AddrPC.Offset = context->Eip;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context->Ebp;
    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrStack.Offset = context->Esp;
    frame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
    image = IMAGE_FILE_MACHINE_AMD64;
    frame.AddrPC.Offset = context->Rip;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context->Rsp;
    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrStack.Offset = context->Rsp;
    frame.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
    image = IMAGE_FILE_MACHINE_IA64;
    frame.AddrPC.Offset = context->StIIP;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context->IntSp;
    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrBStore.Offset = context->RsBSP;
    frame.AddrBStore.Mode = AddrModeFlat;
    frame.AddrStack.Offset = context->IntSp;
    frame.AddrStack.Mode = AddrModeFlat;
#else
#error "This platform is not supported."
#endif
    IMAGEHLP_SYMBOL64 *symbol = (IMAGEHLP_SYMBOL64 *)malloc(sizeof(IMAGEHLP_SYMBOL64)+(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR));
    symbol->MaxNameLength = TRACE_MAX_FUNCTION_NAME_LENGTH;
    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 
    IMAGEHLP_LINE64 *line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
    line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    while (StackWalk64(image, process, thread, &frame, context, NULL, NULL, NULL, NULL))
    {
        DWORD64 displacement64;
        if (SymGetSymFromAddr64(process, frame.AddrPC.Offset, &displacement64, symbol))
        {
            DWORD displacement;
            if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &displacement, line))
            {
                printf("\tat %s in %s: line: %lu: address: 0x%0X\n", symbol->Name, line->FileName, line->LineNumber, symbol->Address);
            }
            else
            {
                printf("Error from SymGetLineFromAddr64: %lu.\n", GetLastError());
            }
        }
        else
        {
            printf("Error from SymGetSymFromAddr64: %lu.\n", GetLastError());
        }
    }
    return EXCEPTION_EXECUTE_HANDLER;
}

static void threadFunction(void *param)
{
    __try
    {
        function0();
    }
    __except (FatalExceptionFilter(GetExceptionInformation(), GetExceptionCode()))
    { }
}

int _tmain(int argc, _TCHAR* argv[])
{
    _beginthread(threadFunction, 0, NULL);
    printf("Press any key to exit.\n");
    cin.get();
    return 0;
}

输出:

Press any key to exit.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.

我对 SymGetSymFromAddr64 为什么失败感到有点困惑。有什么想法吗?

126 应该是缺失的依赖项,但我在适当的文件夹中有 DLL...我正在使用 Win32 平台调试构建的 Windows 8.1 x64 PC 上的 MSVC++ 控制台应用程序中运行这一切。那么是什么导致了这个问题?

更新:Dependency walker 告诉我它找不到 API-MS-WIN-SERVICE-PRIVATE-L1-1-1.DLL

最佳答案

你的代码有同样的问题。

修复它:

HANDLE process = GetCurrentProcess();
SymInitialize( process,NULL,TRUE );

注意:现在,SymGetLineFromAddr64 对某些大地址失败,错误为 487 (ERROR_INVALID_ADDRESS)

使用以下内容进行跟踪:

printf("Error from SymGetLineFromAddr64: %lu for address 0x%I64x.\n",
       GetLastError(),
       frame.AddrPC.Offset);

编辑:当我在 Visual Studio 中使用 Go to Disassembly 并输入使 SymGetLineFromAddr64 失败的第一个地址时(这里是 0x000000005a03da08),它显示了源代码代码:

f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\throw.cpp

关于c++ - 为什么 SymGetSymFromAddr64 不工作?它返回错误代码 126,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22481126/

相关文章:

winapi - 需要在VB6中找到我自己的进程ID

visual-studio-2010 - 64位windows平台WIN32预处理器定义

c++ - 将 Lambda 存储在类段错误中

c - 如何默认定义所有 winapi 以将字符串视为 UNICODE?

c++ - 如何初始化一个长度等于 const int 方法返回值的数组?

java - 在 JNA 定义需要回调的地方传递原始函数指针?

关于函数参数和递归的类和默认值的 C++ 问题

c++ - Shell使用特定的工作目录执行cmd提示符

c++ - 带有 GLUT 的 OpenGL - 黑屏

c++ - 访问另一个 QThread 中的对象成员