Ubuntu(Linux)现场C++程序频繁崩溃,直接照做就能排查的极简实战流程,不废话、全是现场能用的步骤,按顺序执行即可。
一、先立刻开启崩溃转储(必须做)
让客户终端执行:
bash
ulimit -c unlimited
然后在同一个终端里启动你的程序,崩溃后会生成 core 文件(core.xxx)。
作用:直接定位崩溃在哪一行、哪个函数。
二、用 gdb 直接看崩溃栈(最快定位)
bash
gdb ./你的程序 core.xxx
进入gdb后输入:
gdb
bt
会打印完整调用栈,直接看到崩溃行号。
常见崩溃原因(Ubuntu下90%都是这些):
1. SIGSEGV:空指针、野指针、数组越界、use-after-free
2. SIGABRT:double free、堆损坏、assert失败
3. SIGBUS:内存对齐错误、硬件/驱动问题
4. 栈溢出:递归太深、栈上开大数组
三、加日志(现场最稳、最通用)
在关键位置加线程安全日志,打印:
- 函数进入/退出
- 指针是否为空
- 数组下标、大小
- 文件/串口/网络返回值
- 线程ID
日志必须:
- 写到文件
- 每次写 flush
- 不要用cout缓存,崩了日志出不来
四、用 AddressSanitizer(内存问题神器,必试)
编译时加参数:
bash
g++ -fsanitize=address -fno-omit-frame-pointer -g main.cpp -o app
直接运行,越界、use-after-free、double free 都会直接报位置。
优点:
- 比valgrind快很多
- 现场可直接跑
- 几乎能抓到所有内存bug
五、线程问题排查(随机崩溃、难复现)
Ubuntu下用TSan:
bash
g++ -fsanitize=thread -g main.cpp -o app
运行后会直接报:
- 数据竞争
- 死锁风险
- 未加锁共享变量
六、Ubuntu现场环境排查(非常关键)
1. 系统位数:32/64?你编译的是否一致?
2. GCC/G++版本:本地高版本,现场低版本 → 崩溃、行为异常
3. 依赖库版本(Qt、protobuf、opencv、串口库等)
bash
ldd 你的程序
看.so是否缺失、版本不对
4. 权限:串口、USB、网卡、配置文件读写权限不足
5. 资源泄漏:
bash
top # 看内存是否一直涨
lsof -p 进程号 # 看句柄泄漏
七、Ubuntu 常用排查命令(直接抄)
bash
# 看系统内核崩溃信息
dmesg | grep 你的程序名
# 看程序崩溃信号
dmesg | grep segfault
# 看依赖库
ldd ./app
# 看系统日志
journalctl -xe | grep 你的程序
八、标准排查顺序(你按这个做,不会乱)
1. 开core,gdb bt → 拿到崩溃栈
2. 看崩溃类型:指针/内存/线程/库/权限
3. 加日志锁定范围
4. ASan跑一遍,抓内存bug
5. 核对Ubuntu环境、依赖库、权限
6. 代码检查:指针、智能指针、锁、数组边界、释放后置空