一 gdb调试段错误
我们在linux开发时,经常遇到段错误,发生这种情况一般是因为访问了非法的内存地址,例如数组越界;使用未开辟内存的指针,例如
int *p;
if(p==NULL){
xxx;//必定报错,因为p并未开辟内存
}
这些都会出现段错误的问题。那么,我们遇到段错误时如何精确找到出问题的行号?
1 方法1
ulimit -a //先查看core file size的大小,一般为0
ulimit -c unlimited //修改大小为无限制
./mytest //执行可执行程序,生成core文件
gdb mytest core.177474 //执行生成的core.177474文件,该文件的名字由系统指定。(该语句可以使用gdb -c core.231206 mytest 代替)
//找到#0的那几行分析:就是问题的所在。下面我的例子可以忽略,这里贴出来的目的是想表达,发生段错误,但是编译器可能报的错误不是段错误。
//一般我们只需要分析#0~#n的行,这些行都是你代码调用的顺序,在调用的顺序中发生了段错误,然后自己一步步排查确定是哪一行发生段错误即可。
//这里我贴出我段错误时,它报了以下错误,大概意思是,gcc与libstdc++的版本不一致的问题(因为我调用过list的pushback函数)。:
#0 0x00007f5be215d11f in std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*) ()
from /lib64/libstdc++.so.6
//查看gcc版本信息,即libstdc++库版本
strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
//上面的错误,实际上我是因为在构造使用了没有初始化的指针,但是delete时,在析构仍然判断是否为空,导致段错误和核心已转存。
//被编译器报的错搞得一头雾水。方法是使用VSCODE调试找到的原因
2 方法2
第二种方法是我比较喜欢用的方法,因为对于项目比较大时,上面生成的core文件就非常的大,所以对电脑不太好。
gdb ./a.out
// 1 当发生段错误时,直接列出所有的栈信息,即下面命令:
bt
//2 此时有许多函数和库,我们从底部依次往上看,依次代表先调用的函数,
//一般底部函数由main开始或者系统调用(实际还是因为main调用了呗),然后依次往上分析自己每个可能出错的函数,这样非常容易解决段错误
最终是.hpp头文件中找到了段错误的原因。下面的这些行数都是有可能出现段错误,需要我们自己去排查,不过行数并不多。