加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

windows / c:如何从信号处理程序中获取有用的堆栈跟踪?

发布时间:2020-12-14 05:44:36 所属栏目:Windows 来源:网络整理
导读:我有一个 Windows / C应用程序(使用JUCE),我想在应用程序崩溃时将堆栈跟踪转储到文件中.在我的初始化代码中,我得到了: signal(SIGABRT,abortHandler);signal(SIGSEGV,abortHandler);signal(SIGILL,abortHandler);signal(SIGFPE,abortHandler); 然后我的处理
我有一个 Windows / C应用程序(使用JUCE),我想在应用程序崩溃时将堆栈跟踪转储到文件中.在我的初始化代码中,我得到了:

signal(SIGABRT,abortHandler);
signal(SIGSEGV,abortHandler);
signal(SIGILL,abortHandler);
signal(SIGFPE,abortHandler);

然后我的处理程序看起来像:

void abortHandler(int signum)
{
    juce::File log("stacktrace.txt");

    log.appendText(juce::SystemStats::getStackBacktrace());

    exit(signum);
}

但是,生成的堆栈跟踪不是发生崩溃的线程:

0: AudulusDebug32: juce::SystemStats::getStackBacktrace + 0x7f
1: AudulusDebug32: abortHandler + 0x61
2: AudulusDebug32: _XcptFilter + 0x1e3
3: AudulusDebug32: __tmainCRTStartup + 0x15f
4: AudulusDebug32: WinMainCRTStartup + 0xd
5: BaseThreadInitThunk + 0xe
6: RtlInitializeExceptionChain + 0x84
7: RtlInitializeExceptionChain + 0x5a

在内部,getStackBacktrace执行以下操作:

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

    void* stack[128];
    int frames = (int) CaptureStackBackTrace (0,numElementsInArray (stack),stack,nullptr);

有没有办法让崩溃发生的线程(或所有线程)获得堆栈跟踪?

解决方法

正如@HansPassant建议的那样,我的解决方案是:

SetUnhandledExceptionFilter(TopLevelExceptionHandler);

在TopLevelExceptionHandler中,我使用StackWalk64而不是调用CaptureStackBackTrace,它允许您指定要移动的堆栈(而不是仅假设当前堆栈).

这是代码:

LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
    std::ofstream f;
    f.open("stacktrace.txt",std::ios::out | std::ios::trunc);

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

    // StackWalk64() may modify context record passed to it,so we will
    // use a copy.
    CONTEXT context_record = *pExceptionInfo->ContextRecord;
    // Initialize stack walking.
    STACKFRAME64 stack_frame;
    memset(&stack_frame,sizeof(stack_frame));
    #if defined(_WIN64)
    int machine_type = IMAGE_FILE_MACHINE_AMD64;
    stack_frame.AddrPC.Offset = context_record.Rip;
    stack_frame.AddrFrame.Offset = context_record.Rbp;
    stack_frame.AddrStack.Offset = context_record.Rsp;
    #else
    int machine_type = IMAGE_FILE_MACHINE_I386;
    stack_frame.AddrPC.Offset = context_record.Eip;
    stack_frame.AddrFrame.Offset = context_record.Ebp;
    stack_frame.AddrStack.Offset = context_record.Esp;
    #endif
    stack_frame.AddrPC.Mode = AddrModeFlat;
    stack_frame.AddrFrame.Mode = AddrModeFlat;
    stack_frame.AddrStack.Mode = AddrModeFlat;

    juce::HeapBlock<SYMBOL_INFO> symbol;
    symbol.calloc(sizeof(SYMBOL_INFO) + 256,1);
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    while (StackWalk64(machine_type,GetCurrentProcess(),GetCurrentThread(),&stack_frame,&context_record,&SymFunctionTableAccess64,&SymGetModuleBase64,NULL)) {

        DWORD64 displacement = 0;

        if (SymFromAddr(process,(DWORD64)stack_frame.AddrPC.Offset,&displacement,symbol))
        {
            IMAGEHLP_MODULE64 moduleInfo;
            juce::zerostruct(moduleInfo);
            moduleInfo.SizeOfStruct = sizeof(moduleInfo);

            if (::SymGetModuleInfo64(process,symbol->ModBase,&moduleInfo))
                f << moduleInfo.ModuleName << ": ";

            f << symbol->Name << " + 0x" << String::toHexString((juce::int64)displacement) << std::endl;
        }

    }

    return EXCEPTION_CONTINUE_SEARCH;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读