《Linux部分》
【Linux => Debug模式】
测试:https://github.com/bombela/backward-cpp
仅头文件的库,配合#define BACKWARD_HAS_BFD 1和sudo apt install binutils-dev
可以实现Debug下精准找点。
也有apt-get install libdw-dev(#define BACKWARD_HAS_DW 1)和
apt-get install libdwarf-dev(#define BACKWARD_HAS_DWARF 1)这两个没测试。

使用方法为:
#define BACKWARD_HAS_BFD 1
#include "backward.hpp"
#include <csignal>
#include <iostream>
#include <thread>
#include <fstream>

void sig_handler(int sig)
{
    backward::StackTrace st;
    st.load_here(32);
    backward::Printer p;
    p.print(st);

    std::ofstream fs("stacktrace.log");
    p.print(st, fs); 
    fs.close();

    exit(1);
}

void th_sim()
{
    std::this_thread::sleep_for(std::chrono::seconds(5));
    // throw "Erro Auto";
    int* p = nullptr;
    *p = 33;
}

int main()
{
    signal(SIGSEGV, sig_handler);
    signal(SIGABRT, sig_handler);
    signal(SIGFPE, sig_handler);

    std::thread t(th_sim);
    std::cout << "Done" << std::endl;
    t.join();
    return 0;
}

编译链接:target_link_libraries(dmeo PRIVATE bfd dl)

《Windows部分》
【Windows => Debug模式】
#include "backward.hpp"
#include <windows.h>
使用方法:

LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exception)
{
    backward::StackTrace st;
    st.load_from(exception->ContextRecord);
    backward::Printer p;

    // 输出到控制台
    p.print(st, std::cerr);

    // 输出到文件
    std::ofstream fs("stacktrace.log");
    p.print(st, fs);
    fs.close();

    return EXCEPTION_EXECUTE_HANDLER;   // 终止程序
}

显示初始化:backward::SignalHandling sh;而且必须在SetUnhandledExceptionFilter(ExceptionHandler); 后面。

如下:
#include <iostream>
#include <thread>
#include "backward.hpp"
#include <windows.h>

using namespace std;

LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exception)
{
    backward::StackTrace st;
    st.load_from(exception->ContextRecord);
    backward::Printer p;

    // 输出到控制台
    p.print(st, std::cerr);

    // 输出到文件
    std::ofstream fs("stacktrace.log");
    p.print(st, fs);
    fs.close();

    return EXCEPTION_EXECUTE_HANDLER;   // 终止程序
}

void th_sim()
{
    std::this_thread::sleep_for(std::chrono::seconds(5));
    // throw "Erro Auto";
    int* p = nullptr;
    *p = 33;
}

int main()
{
    SetUnhandledExceptionFilter(ExceptionHandler);   // 注册全局异常处理
    backward::SignalHandling sh;
    // std::set_terminate(terminate_handler);
    std::thread t(th_sim);
    std::cout << "Done" << std::endl;
    t.join();
    return 0;
}
编译链接:
target_link_libraries(dumpdemo PRIVATE DbgHelp)
【Windows => Release模式】
实际测试,如果想生成dmp文件,就不能使用backward库(两者选一个)(不使用backward::SignalHandling sh;)。
void CreateMiniDump(EXCEPTION_POINTERS* exception) {
    HANDLE hFile = CreateFile("crash114.dmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        return;
    };
    MINIDUMP_EXCEPTION_INFORMATION info;
    info.ThreadId = GetCurrentThreadId();
    info.ExceptionPointers = exception;
    info.ClientPointers = TRUE;
    MiniDumpWriteDump(
        GetCurrentProcess(), GetCurrentProcessId(), hFile,
        MiniDumpNormal, &info, NULL, NULL
        );
    CloseHandle(hFile);
}
使用backward堆栈信息打印有限,如下(测试代码见上方):
Done
Stack trace (most recent call last):
#3    Object "", at 00007FFBD4A4E8D7, in BaseThreadInitThunk
#2    Object "", at 00007FFBD31C37B0, in wcsrchr
试图访问无效的地址。

#1    Object "", at 00007FF691A2208B, in  ??
试图访问无效的地址。

#0    Object "", at 00007FF691A27EC2, in  ??
而使用WinDbg分析Dump文件,信息如下:
FILE_IN_CAB:  crash114.dmp

CONTEXT:  (.ecxr)
rax=0000000000000000 rbx=0000019f92279e60 rcx=00000018c2d828f9
rdx=00000018ca1b2b0e rsi=00004e94914f0000 rdi=000009ac1b967bb8
rip=00007ff7b2f41682 rsp=00000084c57ff970 rbp=0000000000000000
 r8=0000000000000083  r9=000000007ffe7000 r10=0000000000000001
r11=fffffffff8bcfdeb r12=0000000000000000 r13=0000000000000000
r14=b2f4fc0794908cf3 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
dumpdemo+0x1682:
00007ff7`b2f41682 c70021000000    mov     dword ptr [rax],21h ds:00000000`00000000=????????
Resetting default scope

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ff7b2f41682 (dumpdemo+0x0000000000001682)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000001
   Parameter[1]: 0000000000000000
Attempt to write to address 0000000000000000

PROCESS_NAME:  dumpdemo.exe

WRITE_ADDRESS:  0000000000000000 

ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p            0x%p                    %s

EXCEPTION_CODE_STR:  c0000005

EXCEPTION_PARAMETER1:  0000000000000001

EXCEPTION_PARAMETER2:  0000000000000000

STACK_TEXT:  
00000084`c57ff970 00007ff7`b2f4126b     : 000009aa`f19089b8 0000019f`92279e60 00000000`00000000 00000000`00000000 : dumpdemo+0x1682
00000084`c57ff9b0 00007ffb`d31c37b0     : 0000019f`92275720 00000000`00000000 00000000`00000000 00000000`00000000 : dumpdemo+0x126b
00000084`c57ff9e0 00007ffb`d4a4e8d7     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ucrtbase!thread_start<unsigned int (__cdecl*)(void *),1>+0x30
00000084`c57ffa10 00007ffb`d5b314fc     : 00000000`00000000 00000000`00000000 000004f0`fffffb30 000004d0`fffffb30 : kernel32!BaseThreadInitThunk+0x17
00000084`c57ffa40 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2c


STACK_COMMAND:  ~4s; .ecxr ; kb

SYMBOL_NAME:  dumpdemo+1682

MODULE_NAME: dumpdemo

IMAGE_NAME:  dumpdemo.exe

FAILURE_BUCKET_ID:  NULL_POINTER_WRITE_c0000005_dumpdemo.exe!Unknown

OS_VERSION:  10.0.26100.1

BUILDLAB_STR:  ge_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {78a98d01-ecf2-dbb7-c5b9-5fb9cd0cc5e2}

Followup:     MachineOwner
---------

0:004> .ecxr
rax=0000000000000000 rbx=0000019f92279e60 rcx=00000018c2d828f9
rdx=00000018ca1b2b0e rsi=00004e94914f0000 rdi=000009ac1b967bb8
rip=00007ff7b2f41682 rsp=00000084c57ff970 rbp=0000000000000000
 r8=0000000000000083  r9=000000007ffe7000 r10=0000000000000001
r11=fffffffff8bcfdeb r12=0000000000000000 r13=0000000000000000
r14=b2f4fc0794908cf3 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
dumpdemo+0x1682:
00007ff7`b2f41682 c70021000000    mov     dword ptr [rax],21h ds:00000000`00000000=????????
0:004> kb
  *** Stack trace for last set context - .thread/.cxr resets it
 # RetAddr               : Args to Child                                                           : Call Site
00 00007ff7`b2f4126b     : 000009aa`f19089b8 0000019f`92279e60 00000000`00000000 00000000`00000000 : dumpdemo+0x1682
01 00007ffb`d31c37b0     : 0000019f`92275720 00000000`00000000 00000000`00000000 00000000`00000000 : dumpdemo+0x126b
02 00007ffb`d4a4e8d7     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ucrtbase!thread_start<unsigned int (__cdecl*)(void *),1>+0x30
03 00007ffb`d5b314fc     : 00000000`00000000 00000000`00000000 000004f0`fffffb30 000004d0`fffffb30 : kernel32!BaseThreadInitThunk+0x17
04 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2c