Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >linux下的程序调试方法汇总

linux下的程序调试方法汇总

作者头像
战神伽罗
发布于 2019-07-24 06:38:05
发布于 2019-07-24 06:38:05
4K00
代码可运行
举报
运行总次数:0
代码可运行

搞电子都知道,电路不是焊接出来的,是调试出来的。程序员也一定认同,程序不是写出来的,是调试出来的。那么调试工具就显得尤为重要,linux作为笔者重要的开发平台,在linux中讨论调试工具主要是为那些入门者提供一些帮助。调试工具能让我们能够监测、控制和纠正正在运行的程序。我们在运行一些程序的时候,可能被卡住或出现错误,或者运行过程或结果,没能如我们预期,此时,最迫切需要明白究竟发生了什么。为了修复程序,剖析和了解程序运行的细节, 调试工具就成为了我们的必备工具,工于善其事,必先利其器。在Linux下的用户空间调试工具主要有系统工具和专门调试工具:'print' 打印语句,这是新手最常用的,也是最不提倡使用的;查询 (/proc, /sys 等)系统的虚拟文件查看,这个方法有局限性;跟踪 (strace/ltrace)工具使用这个比较普遍,值得提倡;Valgrind (memwatch)内存排除工具,在内存排除方面比较独到,是内存排错的法宝;GDB大名鼎鼎的程序调试工具,这个是个全能的工具,没有完不成的,只有你不知道的。

1.'print' 语句

这是一个基本的调试问题的方法。 我们在程序中怀疑的地方插入print语句来了解程序的运行流程控制流和变量值的改变。 这是一个最简单的技术, 它的缺点。 需要进行程序编辑,添加'print'语句,必须重新编译,重新运行来获得输出。若需要调试的程序比较大,这将是一个耗时费力的方法。

2. 查询

在某些情况下,我们需要弄清楚在一个运行在内核中的进程的状态和内存映射。为了获得这些信息,我们不需要在内核中插入任何代码。 相反,可以用 /proc 文件系统。在/proc的伪文件系统,保留系统启动运行就收集的运行时信息 (cpu信息, 内存容量等)。

ls -l /proc'的输出结果,通过对 系统中运行的每一个进程在/proc文件系统中有一个以进程id命名的项。每个进程的细节信息可以在进程id对应的目录下的文件中获得。也可以'ls /proc/pid'的输出

解释/proc文件系统内的所有条目超出了本文的范围。一些有用的列举如下:

  • /proc/cmdline -> 内核命令行
  • /proc/cpuinfo -> 关于处理器的品牌,型号信息等
  • /proc/filesystems -> 文件系统的内核支持的信息
  • /proc/<pid>/cmdline -> 命令行参数传递到当前进程
  • /proc/<pid>/mem -> 当前进程持有的内存
  • /proc/<pid>/status -> 当前进程的状态

3. 跟踪

strace的和ltrace是两个在Linux中用来追踪程序的执行细节的跟踪工具。

strace:

strace拦截和记录系统调用及其接收的信号。对于用户,它显示了系统调用、传递给它们的参数和返回值。strace的可以附着到已在运行的进程或一个新的进程。它作为一个针对开发者和系统管理员的诊断、调试工具是很有用的。它也可以用来当做一个通过跟踪不同的程序调用来了解系统的工具。这个工具的好处是不需要源代码,程序也不需要重新编译。

使用strace的基本语法是:

strace 命令

strace有各种各样的参数。可以检查看strace的手册页来获得更多的细节。

strace的输出非常长,我们通常不会对显示的每一行都感兴趣。我们可以用'-e expr'选项来过滤不想要的数据。

用 '-p pid' 选项来绑到运行中的进程.

用'-o'选项,命令的输出可以被重定向到文件。

strace过滤成只有系统调用的输出

ltrace:

ltrace跟踪和记录一个进程的动态(运行时)库的调用及其收到的信号。它也可以跟踪一个进程所作的系统调用。它的用法是类似与strace。

ltrace command

'-i' 选项在调用库时打印指令指针。

'-S' 选项被用来现实系统调用和库调用

所有可用的选项请参阅ltrace手册。

ltrace捕捉'STRCMP'库调用的输出

4. Valgrind

Valgrind是一套调试和分析工具。它的一个被广泛使用的默认工具——'Memcheck'——可以拦截malloc(),new(),free()和delete()调用。换句话说,它在检测下面这些问题非常有用:

  • 内存泄露
  • 重释放
  • 访问越界
  • 使用未初始化的内存
  • 使用已经被释放的内存等。

它直接通过可执行文件运行。

Valgrind也有一些缺点,因为它增加了内存占用,会减慢你的程序。它有时会造成误报和漏报。它不能检测出静态分配的数组的访问越界问题。

为了使用它,首先请下载并安装在你的系统上。可以使用操作系统上的包管理器来安装。

使用命令行安装需要解压缩和解包下载的文件。

  1. tar -xjvf valgring-x.y.z.tar.bz2 (where x.y.z is the version number you are trying to install)

进入新创建的目录(的valgrind-XYZ)内运行以下命令:

  1. ./configure
  2. make
  3. make install

让我们通过一个小程序(test.c)来理解valgrind怎么工作的:

  1. #include <stdio.h>
  2. void f(void)
  3. {
  4. int x = malloc(10 * sizeof(int));
  5. x[10] = 0;
  6. }
  7. int main()
  8. {
  9. f();
  10. return 0;
  11. }

编译程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
gcc -o test -g test.c

现在我们有一个可执行文件叫做'test'。我们现在可以用valgrind来检测内存错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
valgrind –tool=memcheck –leak-check=yes test

这是valgrind呈现错误的输出:

valgrind显示堆溢出和内存泄漏的输出

正如我们在上面看到的消息,我们正在试图访问函数f未分配的内存以及分配尚未释放的内存。

5. GDB

GDB是来自自由软件基金会的调试器。它对定位和修复代码中的问题很有帮助。当被调试的程序运行时,它给用户控制权去执行各种动作, 比如:

  • 启动程序
  • 停在指定位置
  • 停在指定的条件
  • 检查所需信息
  • 改变程序中的数据 等。

你也可以将一个崩溃的程序coredump附着到GDB并分析故障的原因。

GDB提供很多选项来调试程序。 然而,我们将介绍一些重要的选择,来感受如何开始使用GDB。

如果你还没有安装GDB,可以在这里下载:GDB官方网站

编译程序:

为了用GDB调试程序,必须使用gcc的'-g'选项进行编译。这将以操作系统的本地格式产生调试信息,GDB利用这些信息来工作。

下面是一个简单的程序(example1.c)执行被零除用来显示GDB的用法:

  1. #include
  2. int divide()
  3. {
  4. int x=5, y=0;
  5. return x / y;
  6. }
  7. int main()
  8. {
  9. divide();
  10. }

展示GDB用法的例子

调用 GDB:

通过在命令行中执行'gdb'来启动gdb:

调用 gdb

调用后, 它将等待终端命令并执行,直到退出。

如果一个进程已经在运行,你需要将GDB连接到它上面,可以通过指定进程ID来实现。假设程序已经崩溃,要分析问题的原因,则用GDB分析core文件。

启动程序:

一旦你在GDB里面,使用'run'命令来启动程序进行调试。

给程序传参数:

使用'set args'给你的程序传参数,当程序下次运行时将获得该参数。'show args'将显示传递给程序的参数。

检查堆栈:

每当程序停止,任何人想明白的第一件事就是它为什么停止,以及怎么停在那里的。该信息被称为反向跟踪。由程序产生每个函数调用和局部变量,传递的参数,调用位置等信息一起存储在堆栈内的数据块种,被称为一帧。我们可以使用GDB来检查所有这些数据。 GDB从最底层的帧开始给这些帧编号。

  • bt: 打印整个堆栈的回溯
  • bt 打印n个帧的回溯
  • frame : 切换到指定的帧,并打印该帧
  • up : 上移'n'个帧
  • down : 下移'n'个帧 ( n默认是1)
检查数据:

程序的数据可以在里面GDB使用'print'命令进行检查。例如,如果'x'是调试程序内的变量,'print x'会打印x的值。

检查源码:

源码可以在GDB中打印。默认情况下,'list'命令会打印10行代码。

  • list : 列出'linenum'行周围的源码
  • list : 从'function'开始列出源码
  • disas : 显示该函数机器代码
停止和恢复程序:

使用GDB,我们可以在必要的地方设置断点,观察点等来停止程序。

  • break : 在'location'设置一个断点。当在程序执行到这里时断点将被击中,控制权被交给用户。
  • watch : 当'expr'被程序写入而且它的值发生变化时GDB将停止
  • catch : 当'event'发生时GDB停止
  • disable : 禁用指定断点
  • enable : 启用指定断点
  • delete : 删除 断点/观察点/捕获点。 如果没有传递参数默认操作是在所有的断点
  • step: 一步一步执行程序
  • continue: 继续执行程序,直到执行完毕
退出 GDB:

用'quit'命令还从GDB中退出。

GDB还有更多的可用选项。里面GDB使用help选项了解更多详情。

在GDB中获得帮助

总结

在这篇文章中,我们已经看到不同类型的Linux用户空间的调试工具。总结以上所有内容,如下是什么时候使用该什么的快速指南:

  • 基本调试,获得关键变量 - print 语句
  • 获取有关文件系统支持,可用内存,CPU,运行程序的内核状态等信息 - 查询 /proc 文件系统
  • 最初的问题诊断,系统调用或库调用的相关问题,了解程序流程 – strace / ltrace
  • 应用程序内存空间的问题 – valgrind
  • 检查应用程序运行时的行为,分析应用程序崩溃 – gdb
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
linux后台开发常用调试工具
一、编译阶段 nm 获取二进制文件包含的符号信息 strings 获取二进制文件包含的字符串常量 strip 去除二进制文件包含的符号 readelf 显示目标文件详细信息 objdump 尽可能反汇编出源代码 addr2line 根据地址查找代码行 二、运行阶段 gdb 强大的调试工具 ldd 显示程序需要使用的动态
李海彬
2018/03/23
3.9K0
Linux调试工具
Printf(“valriable x has value = %d\n”, x)
战神伽罗
2019/07/24
10.1K0
Linux调试工具
Linux后台服务常用诊断命令和方法
vmstat 1  每隔一秒输出系统状态,数据来源/pro/stat,输出各列的含义
洛杉矶
2020/10/23
1.7K0
应用程序崩溃
应用程序崩溃是一个常见的问题,可能是由多种原因引起的,包括内存泄漏、资源耗尽、代码错误等。以下是一些诊断和解决应用程序崩溃的方法:
是山河呀
2025/02/03
1100
全志 Tina Linux 系统调试 使用指南 GDB gdbserver coredump perf strace valgind
适用范围: 本文适用于Tina3.5版本以上软件平台;对硬件环境没有要求,所有Allwinner硬件平台都适 用。 其中,注意linux-5.4内核上暂未支持pstore功能。
韦东山
2022/12/28
2.3K0
Hacker基础之Linux篇:进阶Linux命令二
发音类似<砰>,对黑客而言,这就是成功实施黑客攻击的声音,砰的一声,被<黑>的电脑或手机就被你操纵了
用户1631416
2018/07/25
8270
Hacker基础之Linux篇:进阶Linux命令二
linux环境常用的性能监控和协助开发调试工具
本文介绍了在 Linux 系统中,通过 perf 工具对应用程序进行性能监控的方法和工具。作者从监控方式、监控工具、性能调优、瓶颈诊断等方面进行了详细的阐述。同时,作者还提供了在性能调优过程中的实用技巧和案例,以帮助读者更好地掌握性能调优技巧。本文适合对 Linux 系统性能调优和应用程序性能监控感兴趣的读者阅读。
s1mba
2017/12/26
3.9K0
linux环境常用的性能监控和协助开发调试工具
Linux设备驱动程序(四)——调试技术
由于内核是一个不与特定进程相关的功能集合,所以内核代码无法轻易地放在调试器中执行,而且也很难跟踪跟踪,本章节将介绍监视内核代码并跟踪错误的技术。
Gnep@97
2023/08/10
1.2K0
Linux设备驱动程序(四)——调试技术
Golang程序调试常用方法
一般来说,项目开发过程中,代码编写占开发总时间的40%,剩下的时间基本就是自测和联调的过程。程序出错很正常,关键是如何迅速的去定位它,修掉它。本文将介绍自己程序调试的一些常用方法,这边我以golang为例,总结为望问切闻---debug四部曲。
于顾而言SASE
2024/03/21
2470
Golang程序调试常用方法
GDB调试-从入门实践到原理
在上篇文章中,我们分析了线上coredump产生的原因,其中用到了coredump分析工具gdb,这几天一直有读者在问,能不能写一篇关于gdb调试方面的文章,今天借助此文,分享一些工作中的调试经验,希望能够帮到大家。
高性能架构探索
2022/08/25
3.2K0
GDB调试-从入门实践到原理
掌握GDB调试工具,轻松排除bug
目前release的最新版本为8.0,GDB可以运行在Linux 和Windows 操作系统上。
嵌入式Linux内核
2023/06/28
8360
掌握GDB调试工具,轻松排除bug
GDB调试
约定:对gdb的命令,如果有缩写形式,会在第一次出现的时候小括号内给出缩写,比如运行命令写成run(r);本文中尖括号< >用来表达一类实体,比如<program>表示这个地方可以放置程序;中括号[]表示括号中的内容是可写可不写,比如[=<value>],表示“=<value>”可以有也可以没有(<value>本身又是一类实体);“|”表示或的关系。
玖柒的小窝
2021/12/14
2.2K0
GDB调试
深入探索GDB:Linux下强大的调试神器
GDB,全称GNU Debugger,是一款开源、跨平台的源码级调试工具,尤其在Linux生态系统中占据着举足轻重的地位。GDB支持包括C、C++、Fortran、Ada、Objective-C、Go、D等多种编程语言,能够与GCC、Clang、LLVM等一系列主流编译器无缝集成。无论是针对桌面应用程序、服务器端服务,还是嵌入式系统,GDB都能以其强大的功能和灵活的交互方式,为开发者提供无与伦比的调试体验。
P_M_P
2024/04/25
1.1K0
深入探索GDB:Linux下强大的调试神器
后台开发:核心技术与应用实践 -- 编译与调试
编译与链接的过程可以分解为4个步骤:分别是预处理(Prepressing )、编译(Compilation )、汇编(Assembly )和链接(Linking ),一个helloworld的编译过程如下:
范中豪
2021/03/16
7970
后台开发:核心技术与应用实践 -- 编译与调试
ELF文件-逆向工具
1、ELF文件内容解析 readelf: 可解析ELF文件的所有内容; strings: 查看ELF文件中的字符串; file : 查看ELF文件的信息; nm : 查看ELF文件中的符号信息; ldd : 查看ELF文件所依赖的库文件;
h0cksr
2023/05/17
1.2K0
深入浅出GDB调试器
GDB全称GNU symbolic debugger,它是诞生于GNU开源组织的(同时诞生的还有 GCC、Emacs 等)UNIX及UNIX-like下的调试工具,是Linux下最常用的程序调试器,GDB 支持调试多种编程语言编写的程序,包括C、C++、Go、Objective-C、OpenCL、Ada 等。但是在实际应用中,GDB 更常用来调试C和C++程序。虽然说在Linux系统下我们可以借助诸多集成开发工具来完成程序的编写和调试,但实际上,调试C/C++程序一定是直接或者间接使用GDB完成的。所以说GDB调试几乎可以说是Linux程序员必备的基本技能。本文将手把手教你使用GDB调试程序,并带你深入了解什么是GDB调试器。
mindtechnist
2024/08/08
4850
深入浅出GDB调试器
炫技!bug 排查大曝光,涉及Linux 内核的那种
编写代码只是程序员的工作之一,调试代码的时间甚至会超过编写代码,之前为大家讲解了很多关于系统、架构、编程等方面的内容,这篇文章就为大家全方位展示一次涉及到内核的 bug 排查过程。
用户6543014
2021/03/09
1.7K0
炫技!bug 排查大曝光,涉及Linux 内核的那种
系统设计--内存泄漏该怎么分析?
strace会追踪程序运行时的整个生命周期, 输出每一个系统调用的名字、参数、返回值和执行所消耗的时间等,是高级运维和开发人员排查问题的杀手铜。https://www.cnblogs.com/fadewalk/p/10847068.html
早起的鸟儿有虫吃
2022/01/11
1K0
系统设计--内存泄漏该怎么分析?
吃土记之GDB调试原理
If you are thinking of using complex kernel programming to accomplish tasks, think again. Linux provides an elegant mechanism to achieve all of these things: the ptrace (Process Trace) system call.
早起的鸟儿有虫吃
2023/04/03
1.1K0
吃土记之GDB调试原理
Linux 命令(137)—— strace 命令
strace 命令是一个集诊断、调试、统计于一体的工具,我们可以使用 strace 对程序的系统调用和信号传递的跟踪结果来对程序进行分析,以达到解决问题或者是了解程序工作过程的目的。当然strace 与专业的调试工具比如说 gdb 之类的是没法相比的,因为它不是一个专业的调试器。
恋喵大鲤鱼
2020/04/13
8.5K0
相关推荐
linux后台开发常用调试工具
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验