什么网站做展板的多,东莞专业建站公司费用,经典传奇网页游戏,免费帮忙做网站前面几篇文章学习了链接器相关的内容。现在开始来学习GDB调试。我们的目的是通过这几篇文章将GDB调试完全学会。 文章目录1 为什么需要GDB2 GDB 的常规应用3 GDB调试程序实例4 总结1 为什么需要GDB
什么是GDB#xff1f; GNU项目中的调试器#xff08;gnu debuger#xff0…前面几篇文章学习了链接器相关的内容。现在开始来学习GDB调试。我们的目的是通过这几篇文章将GDB调试完全学会。 文章目录1 为什么需要GDB2 GDB 的常规应用3 GDB调试程序实例4 总结 1 为什么需要GDB
什么是GDB GNU项目中的调试器gnu debuger能够跟踪程序的执行也能够恢复程序执行前的状态 为什么需要GDB 软件不是一次性开发完的是软件就一定有bug所以需要调试工具来定位bug调试是软件开发过程中不可或缺的部分 2 GDB 的常规应用 自定义程序启动的方式指定影响程序运行的参数设置条件断点在条件满足时暂停程序的执行一般为循环中的语句或者递归调用中的语句回溯检查导致程序异常的原因一般是通过分析核心转储文件-core文件动态改变程序执行流定位问题的辅助方式 GDB的启动方式有哪些
直接启动 gdbgdb test.outgdb test.out core 动态连接 gdb test.out pid 在给出gdb具体的调试代码步骤之前我们先来看看两个应用示例 GDB应用示例一 其中设置命令行参数这里如果了解main函数的参数的话应该知道如果不了解命令行参数请参考这篇文章 main函数参数的意义还有一点就是下面两种载入目标程序的命令是一样的效果 其他的用法都很好理解我们不再赘述 GDB应用示例二 上述各个命令的使用方法也很好理解我们只需要注意下图中的两种启动方式同样是等效的 3 GDB调试程序实例
下面就开始使用具体的例子来详细解读GDB调试的过程
我们调试的两个代码为
test.c
#include stdio.h
#include unistd.hextern int* g_pointer; // 外部变量
extern void func(); // 外部函数void test_1()
{printf(test_1() : %p\n, test_1);
}void test_2()
{printf(test_2() : %p\n, test_2);
}void test_3()
{printf(test_3() : %p\n, test_3);
}int main(int argc, char *argv[])
{typedef void(TFunc)();TFunc* fa[] {test_1, test_2, test_3};int i 0;printf(main() : begin...\n);for(i0; iargc; i) //argc代表命令行参数的个数{printf(argv[%d] %s\n, i, argv[i]);}for(i0; i100; i){fa[i%3]();sleep(argc 1); // 如果argc大于1则执行睡眠函数}printf(g_pointer %p\n, g_pointer);func();printf(main() : end...\n);return 0;
}func.c
#include stdio.hint* g_pointer;void func()
{*g_pointer (int)D.T.Software; //注意这里是出错的地方g_pointer是指向0地址但是在这里却对0地址赋值return;
}GDB使用初探-----下面我们暂时先不调试先熟悉熟悉几个命令是如何使用的。 首先对上述程序编译并且运行gcc func.c test.c -o test.out./test.out毫无疑问程序肯定会产生错误如下图 这是在意料之中的毕竟在func.c程序中我们对0地址进行写内容了。那么现在我们开始使用gdb来定位出错误在开启gdb调试之前需要在编译源程序的时候加上-g选项并将程序的崩溃信息转储的core文件这在【软件开发底层知识修炼】六 Binutils辅助工具之- addr2line与strip工具这篇文章中有讲解过。gcc -g test.c func.c -o test.out //重新编译加上调试信息ulimit -c unlimited //让程序在崩溃时产生core文件./test.out //重新运行看看是否产生core文件 很明显核心已转出生成了core文件----注意这是GDB调试需要用的文件 输入命令gdb test.out core 进行调试 从这里我们甚至都直接看到了产生段错误的地方就在func.c程序中的第7行func函数中出的问题。输入quit命令退出当前gdb调试 输入命令gdb 进行调试 输入gdb后再gdb调试模式下输入file test.out 然后字gdb调试模式下输入run显示结果最后部分如下 通过上面的动态图我们很容易发现程序执行的很快瞬间就到了段错误那里。我们回到test.c程序中会发现这段代码中 for(i0; i100; i) { fa[i%3] (); sleep(argc 1); // 如果argc大于1则执行睡眠函数 } 由于sleep参数中argc的参数为1只有./test.out这个参数所以不会睡眠。但是我们可以在gdb中进行设置参数输入命令set args D.T.SoftWare就像下面的动态图一样 很明显我们的程序运行起来变得慢很多这是因为我们加了一个命令行参数D.T.SoftWare现在命令行参数就有两个一个是可执行程序test.out一个是D.T.SoftWare如果这里不明白命令行参数的意思请参考这篇文章main函数参数最后输入ctrl c可以终止程序的执行再输入continue可以继续执行刚刚被终止的程序。 gdb动态连接到一个正在执行的程序然后对其进行调试 还是直接看下面的动图更加好理解 在右边的终端我们运行程序的时候加一个参数D.T.SoftWare这样可以让上述的for循环中的sleep开启让程序执行的慢一点程序执行起来后在左边的终端首先输入ps aux查看我们的程序的pid然后sudo gdb 开启gdb这里加上sudo以root模式开启是因为动态连接正在运行的程序的话就需要以root模式开启gdb进入gdb模式后使用attach pid 这里的pid根据你自己查到的pid写连接到我们运行的程序。在我们连接到程序的一瞬间发现程序的执行停止了使用continue可以继续程序的执行当程序运行到段错误那里gdb可以发现错误说明已经连接到运行中的程序现在可以使用gdb对它进行调试了。怎么调试随你意上面我们也说了几种简单的调试方法。 4 总结
本文只是介绍GDB调试的几种简单用法。下一篇文章会学习GDB的断点调试。
本文章参考狄泰软件学院相关课程 想学习的可以加狄泰软件学院群 群聊号码199546072
学习探讨加个人可以免费帮忙下载CSDN资源 qq1126137994 微信liu1126137994