【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用

前面几篇文章学习了链接器相关的内容。现在开始来学习GDB调试。我们的目的是通过这几篇文章将GDB调试完全学会。

文章目录

  • 1 为什么需要GDB
  • 2 GDB 的常规应用
  • 3 GDB调试程序实例
  • 4 总结

1 为什么需要GDB

  • 什么是GDB?
  • GNU项目中的调试器(gnu debuger)
  • 能够跟踪程序的执行,也能够恢复程序执行前的状态
  • 为什么需要GDB?
  • 软件不是一次性开发完的,是软件就一定有bug,所以需要调试工具来定位bug
  • 调试是软件开发过程中不可或缺的部分

2 GDB 的常规应用

  • 自定义程序启动的方式(指定影响程序运行的参数)
  • 设置条件断点(在条件满足时暂停程序的执行,一般为循环中的语句或者递归调用中的语句)
  • 回溯检查导致程序异常的原因(一般是通过分析核心转储文件-core文件)
  • 动态改变程序执行流(定位问题的辅助方式)

GDB的启动方式有哪些?

  1. 直接启动
  1. gdb
  2. gdb test.out
  3. gdb test.out core
  1. 动态连接
  1. gdb test.out pid

在给出gdb具体的调试代码步骤之前,我们先来看看两个应用示例:

  • GDB应用示例一

在这里插入图片描述

  • 其中设置命令行参数这里,如果了解main函数的参数的话应该知道,如果不了解命令行参数,请参考这篇文章: main函数参数的意义
  • 还有一点就是下面两种载入目标程序的命令是一样的效果
    在这里插入图片描述
  • 其他的用法都很好理解,我们不再赘述
  • GDB应用示例二
    在这里插入图片描述
  • 上述各个命令的使用方法也很好理解,我们只需要注意下图中的两种启动方式同样是等效的:
    在这里插入图片描述

3 GDB调试程序实例

下面就开始使用具体的例子来详细解读GDB调试的过程

我们调试的两个代码为:

  • test.c
#include <stdio.h>
#include <unistd.h>extern 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(i=0; i<argc; i++)   //argc代表命令行参数的个数{printf("argv[%d] = %s\n", i, argv[i]);}for(i=0; i<100; 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.h>int* 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调试需要用的文件
  1. 输入命令:gdb test.out core 进行调试:

在这里插入图片描述

  • 从这里我们甚至都直接看到了产生段错误的地方就在func.c程序中的第7行,func函数中出的问题。
  • 输入quit命令退出当前gdb调试
  1. 输入命令:gdb 进行调试:
  • 输入gdb后再gdb调试模式下输入:file test.out
    在这里插入图片描述
  • 然后字gdb调试模式下输入run,显示结果最后部分如下:
    在这里插入图片描述
  • 通过上面的动态图我们很容易发现,程序执行的很快,瞬间就到了段错误那里。我们回到test.c程序中,会发现这段代码中:
    for(i=0; i<100; 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可以继续执行刚刚被终止的程序。
  1. 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资源):
qq:1126137994
微信:liu1126137994

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422929.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(219):css伪类选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS伪类<…

【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试

上一篇文章我们学习了使用GDB的最基本方法&#xff1a;【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用 本篇文章将学习GDB的断点调试。断点调试是一种非常重要的调试方法。 文章目录1 断点类型2 GDB软件断点调试相关操作2.1 通过函数名设置断点2.2 通过文件名行号…

Informix IDS 11体系操持(918测验)认证指南,第 4 部门: 机能调优(1)

对 IBM Informix Dynamic Server (IDS) 和它的分比如子体系举行调优&#xff0c;以失掉最佳机能。在一个冗长的概述之后&#xff0c;本教程给出了一些关于怎样检查数据库做事器及其子体系的例子。本文是这个分 8 部门的 系列教程 的第 4 部门&#xff0c;这个教程可以帮手您筹办…

前端学习(220):伪元素选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS伪元素&l…

【软件开发底层知识修炼】十六 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变

上一篇文章我们学习了如何使用GDB进行软件断点调试和硬件断点调试&#xff1a;【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试本篇文章继续上一篇文章的学习&#xff0c;如何使用GDB的数据断点监测内存中的变量是否被改变 文章目录1 GDB的数据断点1.1 利…

AllTray-将办法最小化到琐细托盘

Toy Posted in AppsAllTray 是一个很有效的小办法&#xff0c;操纵它你可以将办法的窗口最小化到琐细托盘&#xff0c;从而腾出桌面空间以作它用。此办法主要为那些没有原生供给最小化到琐细托盘成效的办法而预备的。今朝&#xff0c;AllTray 可以在 GNOME、KDE、Xfce、Fluxbox…

【软件开发底层知识修炼】十七 快速学习GDB调试四 使用GDB进行函数调用栈的查看

上一篇文章学习了如何使用GDB数据断点进行内存监测&#xff1a;【软件开发底层知识修炼】十五 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变本篇文章继续上一篇文章的学习&#xff1a;如何使用GDB进行函数调用栈的查看 文章目录1 backtrace和frame2 使用GDB进行函数调…

前端学习(221):字体属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS字体属性…

前端学习(222):文本属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS文本属性…

【软件开发底层知识修炼】十八 快速学习GDB调试五 使用GDB进行调试的一些小技巧

上一篇文章学习了如何使用GDB进行函数调用栈的查看&#xff1a;【软件开发底层知识修炼】十六 快速学习GDB调试四 使用GDB进行函数调用栈的查看本篇文章是GDB调试快速学习系列的最后一篇。将综合前几篇文章做一个小的总结以及介绍一些在调试中使用的小技巧 文章目录1 调试中的小…

MongoDB学习笔记(一) MongoDB介绍及安装

系列目录 MongoDB学习笔记(一) MongoDB介绍及安装MongoDB学习笔记(二) 通过samus驱动实现基本数据操作MongoDB学习笔记(三) 在MVC模式下通过Jqgrid表格操作MongoDB数据MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系MongoDB学习笔记(五) MongoDB文件存取操作MongoDB…

前端学习(224):iconfont矢量库

矢量库 一、如何下载iconfont图标。 在iconfont-阿里巴巴矢量图标库中有多种图标供你选择。比如我们选择其中的一个作为示例。 鼠标悬浮上后会出现三种选择&#xff1a; 1.添加入库&#xff1a;功能和淘宝中的购物…

如何转载别人的博客

前言 对于喜欢逛CSDN的人来说&#xff0c;看别人的博客确实能够对自己有不小的提高&#xff0c;有时候看到特别好的博客想转载下载&#xff0c;但是不能一个字一个字的敲了&#xff0c;这时候我们就想快速转载别人的博客&#xff0c;把别人的博客移到自己的空间里面&#xff0c…

【软件开发底层知识修炼】二十 深入理解可执行程序的结构

上一篇文章记录了GDB调试从入门到熟练掌握的学习全过程。点击链接查看&#xff1a;【软件开发底层知识修炼】十九 GDB调试从入门到熟练掌握超级详细实战教程学习目录 还记得在以前的学习Binutils工具的时候&#xff0c;学习了很多工具来查看可执行程序的结构&#xff0c;那个时…

前端学习(225):尺寸属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS尺寸属性…

前端学习(226):定位使用

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS定位<…

【数据结构与算法-java实现】三 Java数组类实现

上一篇文章学习了&#xff1a;最好、最坏、平均、均摊时间复杂度的计算与分析方法.本片文章学习数组这种结构。由于数组这种结构比较简单&#xff0c;本文直接简单介绍&#xff0c;然后给出两种实现数组类的Java代码:整形数组类与通用性的数组类 由于数组是相比于其他数据结构实…

解决VMware6.5 以上版本安装RHEL 5的自动安装的问题

解决VMware6.5 以上版本安装RHEL 5的自动安装的问题记得在学习 RHEL5的时候&#xff0c;教室里用的VMware5.5.3的版本&#xff0c;在教室里安装的时候是很正常的有步骤的那种&#xff0c;回到寝室后&#xff0c;用我的VMware6.5 安装的时候却发现&#xff0c;完全变成了自动安装…

【软件开发底层知识修炼】二十一 ABI-应用程序二进制接口一

前面学习了可执行程序的结构&#xff0c;点击链接查看上一篇文章&#xff1a;【软件开发底层知识修炼】二十 深入理解可执行程序的结构本篇文章开始新的篇章&#xff0c;学习应用程序的二进制接口-ABI。 文章目录1 什么是ABI&#xff08;Application Binary Interface&#xff…

【软件开发底层知识修炼】二十二 ABI-应用程序二进制接口 二

上一篇文章学习了ABI的相关内容&#xff0c;具体最后分析了不同ABI下结构体的对齐方式的不同。点击链接查看上一篇文章&#xff1a;【软件开发底层知识修炼】二十一 ABI-应用程序二进制接口一本篇文章继续学习ABI相关内容。是上一篇文章的补充&#xff0c;如果没有看过上一篇文…