用GDB调试core文件
1、先让你的项目编译的时候就按debug的方式构建
2、重新编译你的程序
3、运行程序让它生成core文件,这个默认是关闭的,需要手动开启
这个默认是关闭的,需要手动开启,先查看core dump是否被禁用了,0就是禁用了
ulimit -c
开启
ulimit -c unlimited
4、查看core文件生成的位置
cat /proc/sys/kernel/core_pattern
表明 core dump 不是直接写入文件,而是被 apport
处理了。apport
是 Ubuntu 的崩溃报告工具,它会拦截 core dump 并生成自己的崩溃日志,而不会在当前目录下生成 core
文件。
可以临时禁用apport
sudo systemctl stop apport
echo "core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern
5、调试core文件
gdb ./main core
查看完整堆栈情况
bt full
bt full
显示崩溃发生在:
#0 0x000073e589ac5046 in operator() (__closure=0x56c4997c7e80) at /code/CHAT/Utils/DataBaseManager/DBManager.cpp:58
这个 operator()
是一个 std::function<void(MYSQL_RES*)>
绑定的 Lambda,在 DBManager::excuteQuery
里被调用了。
这里的关键点是这里:
M_functor 里 _M_object 是 0x0,意味着 Lambda 可能在 std::function<void(MYSQL_RES*)> 里被调用时已经 指向了一个空对象。
_M_invoker 指向 0x73e589ad6b67,但 _M_functor._M_object == 0x0,说明 std::function<void(MYSQL_RES*)> 可能已经被析构或未初始化。
这个时候我们可以检查一下,看看这个玩意是不是真的已经指向空对象了
p callback
结果确实如此
6、将函数修改为专为异步而生的future对象
重新修改运行发现问题解决了
之前的问题我还是认为是生命周期有问题。