直接用 Sentry 官方 C++ SDK 会失败,因其要求 C++17 且依赖 libcurl、zlib、openssl/mbedtls,而线上环境常缺失或版本不兼容;链接时易现 undefined reference to sentry_init,主因是未正确链接 -lsentry 或动态库路径未配置;安全落地应采用进程外上报:崩溃进程通过 signal handler(仅用 async-signal-safe 函数如 write())写 crash 上下文至文件,由独立守护进程读取并调用 HTTP API 上报。

为什么直接用 Sentry 官方 C++ SDK 会失败
官方 sentry-native SDK 要求 C++17 且依赖 libcurl、zlib、openssl(或 mbedtls),但很多线上 Windows/Linux 服务环境没有预装这些库,或者版本不兼容。更常见的是:链接时提示 undefined reference to sentry_init —— 实际是静态链接时没带 -lsentry,或动态库路径没进 LD_LIBRARY_PATH/PATH。
真正能快速落地的方案,不是硬啃官方 SDK,而是走「进程外上报」:让崩溃进程通过标准输出/临时文件把 crash 上下文交给一个轻量守护进程,再由它调用 HTTP API 上报到 Sentry。
- 避免在崩溃现场做网络请求(可能死锁、内存破坏后调用栈不可靠)
- 不引入额外动态依赖,C++ 项目只加几行信号处理 + 写文件逻辑
- 守护进程可用 Python/Go 写,独立部署,升级维护不影响主程序
如何用 signal handler 捕获崩溃并安全写 dump
不能在 SIGSEGV / SIGABRT 处理函数里调用 std::cout、malloc、printf —— 这些不是 async-signal-safe 函数,会导致二次崩溃。必须用 write() 直接写文件描述符。
示例关键代码(Linux):
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
void sig_handler(int sig) {
int fd = open("/tmp/crash.dump", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) return;
char buf[512];
int n = snprintf(buf, sizeof(buf), "signal:%d\npid:%d\n", sig, getpid());
write(fd, buf, n);
// 可追加寄存器状态(用 ucontext_t)、栈顶地址等
close(fd);
_exit(1); // 不用 exit(),避免调用 atexit 注册函数
}
- 注册前用
sigaltstack()设置备用栈,防止栈溢出时 handler 无栈可用 - Windows 用
SetUnhandledExceptionFilter+MiniDumpWriteDump生成.dmp文件,比文本 dump 更利于后续分析 - 不要记录堆上对象内容(可能已损坏),只记信号、线程 ID、栈指针、模块基址
怎么把 dump 发给 Sentry 的 /api/{org}/{project}/envelope/
守护进程轮询读取 /tmp/crash.dump 或监听 inotify 事件,解析后构造 Sentry Envelope 发送。注意:Sentry v2.0+ 强制要求 envelope 格式,不能直接 POST JSON。
最小 envelope 示例(Python):
import requests
with open("/tmp/crash.dump") as f:
payload = f.read()
envelope = f"""{"event_id": "xxx", "sent_at": "2024-01-01T00:00:00Z"}
{{
"level": "fatal",
"exception": {{
"values": [{{"type": "SIGSEGV", "value": "segmentation fault"}}]
}},
"platform": "native"
}}"""
requests.post(
"https://o123456.ingest.sentry.io/api/123456/envelope/",
headers={"Content-Type": "application/x-sentry-envelope"},
data=envelope,
timeout=5
)
- 必须带
Content-Type: application/x-sentry-envelope,否则 400 -
event_id行末不能有空格,第二行 JSON 必须顶格,两行之间是换行符(不是 \r\n) - 真实项目中建议加重试 + 本地队列(如用 SQLite 存未发成功的 envelope),避免网络抖动丢日志
符号文件(debug symbols)怎么上传才让堆栈可读
没上传 .debug 或 .pdb,Sentry 页面只会显示 0x7f8a1b2c3d4e 这种地址,毫无意义。关键是上传时机和格式要对。
- Linux:编译时加
-g -Og,用objcopy --strip-debug分离 debug info 到.debug文件,再用sentry-cli dify upload上传 - Windows:MSVC 编译后保留
.pdb,上传时指定--include-sources(如果需源码定位) - 必须确保上传的二进制文件 build ID(ELF note / PE timestamp)和线上运行的完全一致,否则 Sentry 匹配失败
- CI 流水线里上传最稳妥;手动上传容易漏版本,也难追溯
符号匹配失败时,Sentry 后台会标为 “missing debug symbol”,但前端不会明确提示——得去 Project Settings → Debug Files 里手动查上传记录和匹配状态。

















