工作上的内容调整,后期会有大量的时间与c/cpp狭路相逢,翻查了一些对于c/cpp的debug知识,发现了这个很强大的命令,本着独学而无友,必孤陋而寡闻的中心思想,将自己这两天对于gdb的理解,认识也包括一些问题总结下来,跟各位同仁一起交流,向大家学习
1、gdb是干什么的?
gdb是linux环境下的标准调试器,最常使用到的功能有(就这两天我用的比较多的):
1、启动并且运行待调试的程序。
2、在待调试的程序中设置断点,查看断点发生时的堆栈信息
3、查看内存地址中的值
2、gdb常用命令
2.1 设置断点:break(b) 断点可以通过函数名、当前文件内的行号来设置,也可以先指定文件名再指定行号,还可以指定与暂停位的偏移量或者用地址来设置。
格式: b 函数名
b 行号
b 文件名:行号
b +偏移量
b -偏移量
b *地址
举例(见截图)
截图之前插个小插曲:
第一版本demo 代码:
#include <iostream>
int addition (int a, int b)
{
int r;
r=a+b;
return (r);
}
int main ()
{
int z;
z = addition (5,3);
cout<< "The result is "<<z;
return 0;
}
很简单,很明白,就是想打出个8.
但是当我用g++进行编译的时候,碎了
不是吧?查看了几次代码,没发现哪里错啊,莫非多年没碰c、cpp的代码,写这么一个简单的都已经2了,,汗啊
google一把,原来是:
This is becuase C++ 1998 requires cout and endl be called 'std::cout' and 'std::endl', or that a proper using directives such as 'using namespace std;' be used.的原因。
这个还真没啥印象,,知道的BS我吧,,唉,枪不打会生锈,代码不编还真是会生疏啊
添加上之后的代码为:
#include <iostream>
using namespace std;
int addition (int a, int b)
{
int r;
r=a+b;
return (r);
}
int main ()
{
int z;
z = addition (5,3);
cout<< "The result is "<<z;
return 0;
}
g++ -g xxx.cpp之后。通过
继续看断点(b)的截图
g++编译之后,会有一个a.out的文件
执行方式见下:
先查看下整个代码信息:list
OK,我们就在addition函数的return 那一行加个断点
ok,这样就表示我们已经在函数的第8行添加了一个断点。再次执行该函数,会在添加断点处停止,可以查看对应的堆栈信息
运行试一试
程序就在断点添加处暂停了
想着举个断点的例子来帮助自己日后回顾,但其实里面也已包含了其他的几个常用的gdb命令,用gdb调试的时候应该也都经常用到吧。
2.2、查看断点所在函数的堆栈信息
还是拿上面的简单的代码举例吧
看下是不是在main函数,整个函数的14行调的addition
list一把
源文件中的确是在第14行调用的addition函数,整个bt查看到的信息的意思就是main函数在第14行调用了addition函数。
2.3、info的使用
例如:
locals查看当前函数的局部变量
arg查看当前函数参数名和值
info f:打印出更加详细的当前栈层信息。这些信息包含:
- 当前堆栈帧地址(什么是堆栈帧呢?)
- 堆栈帧:堆栈中为当前正在运行的函数分配的区域。
- rip地址(rip是什么?后面一起)
- 开发语言(这里很明显是c++)
- 当前函数的参数地址及值,局部变量的地址
using namespace std;
int sub(int c,int d);
int addition (int a, int b)
{
int r;
r=a+b;
sub(a,b);
return (r);
}
int sub(int c,int d)
{
int zo;
zo=c-d;
return (zo);
}
int main ()
{
int z,g;
z = addition (5,3);
g = sub(5,3);
cout<< "The result is "<<z;
return 0;
}
结果:
局部变量的地址是0x7fffc3deof20。被注册保存的信息是rbp和rip以及它们的内存地址空间地址。
参考资料:debug with gdb