Qt应用程序中的C++崩溃/异常处理程序,在Windows上具有线程支持

Jak*_*rde 6 c++ windows crash multithreading exception-handling

我想为我的Qt应用程序制作崩溃/异常处理程序.我已经有处理程序工作(不包括在下面的代码中).问题是,在Windows上,如果飞机坠毁在同一个线程在那里occures,它只能signal()std::set_terminate()被调用.

在Linux上,它似乎默认适用于所有线程.

有没有办法让它适用于Windows上的所有应用程序线程?

#include "mainwindow.h"
#include <QApplication>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <exception>

void seg_handler(int sig)
{
    // Crash/exception handling code
    // ...
    exit(1);
}

void std_handler( void ) {
     seg_handler(1);
}

int main(int argc, char *argv[]) {

    signal(SIGSEGV, seg_handler);
    std::set_terminate( std_handler );

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

Jak*_*rde 5

经过大量研究,加上我对 Windows 操作系统缺乏了解,我终于找到了一个可行的解决方案,可以自动为新线程设置终止函数。

诀窍是创建一个 dll 来处理崩溃/异常。在你的dll中实现保留的DllMain()函数。每次有新线程或进程附加到主进程时,此函数都会收到通知。该fdwReason参数保存有关事件的信息。

  • 新线程:DLL_THREAD_ATTACH
  • 新流程:DLL_PROCESS_ATTACH

在 dll 中实现终止处理程序,并为启动的每个线程或进程调用signal()和。std::set_terminate()

BOOL WINAPI DllMain(
  _In_ HINSTANCE hinstDLL,
  _In_ DWORD     fdwReason,
  _In_ LPVOID    lpvReserved) {
    if (fdwReason==DLL_THREAD_ATTACH) {
        signal(SIGSEGV, seg_handler);
        std::set_terminate( std_handler );
    }
    if (fdwReason==DLL_PROCESS_ATTACH) {
        signal(SIGSEGV, seg_handler);
        std::set_terminate( std_handler );
    }
    return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

我的处理程序如下所示:

#include <windows.h>
#include "StackWalker.h"
#include <signal.h>
#include <DbgHelp.h>
#include <iostream>
#include <qdebug.h>

void seg_handler(int sig) {
    // Simple callstack
    unsigned int   i;
    void         * stack[ 100 ];
    unsigned short frames;
    SYMBOL_INFO  * symbol;
    HANDLE         process;

    process = GetCurrentProcess();
    SymInitialize( process, NULL, TRUE );
    frames               = CaptureStackBackTrace( 0, 100, stack, NULL );
    symbol               = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
    symbol->MaxNameLen   = 255;
    symbol->SizeOfStruct = sizeof( SYMBOL_INFO );

    for( i = 0; i < frames; i++ ) {
        SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
        printf( "%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address );
    }

    free( symbol );

    // Detailed callstack/crashinfo
    StackWalker sw;
    sw.ShowCallstack(GetCurrentThread());
    exit(1);
}

void std_handler( void ) {
     seg_handler(1);
}
Run Code Online (Sandbox Code Playgroud)

上面的处理程序使用StackWalker

编辑:

当然,您还需要将终止处理程序添加到主线程中:

int main(int argc, char *argv[]) {
    CALL_LOGGER();
    signal(SIGSEGV, seg_handler);
    std::set_terminate( std_handler );
    return runapp(argc, argv);
}
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助

-雅各布