《C语言程序设计进阶教程》一2.7 在DDD(命令行调试程序)上检测调用栈

简介: 本文讲的是C语言程序设计进阶教程一2.7 在DDD(命令行调试程序)上检测调用栈,本节书摘来华章计算机《C语言程序设计进阶教程》一书中的第2章,第2.6.2节, Intermediate C Programming[美] 陆永祥(Yung-Hsiang Lu) 著 徐东 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.7 在DDD(命令行调试程序)上检测调用栈

本文讲的是C语言程序设计进阶教程一2.7 在DDD(命令行调试程序)上检测调用栈,在编辑器中输入下面的程序,并把名字存为p1.c
screenshot
screenshot
不要担心还不能完全理解main函数中的argv,这将会在之后讨论。在Linux终端下使用下面的命令创建可执行文件:
screenshot
这里使用gcc将C程序(p1.c)的源文件转化为计算机可以理解的可执行文件。添加-g启用调试,这样我们可以检验调用栈。添加-Wall和-Wshadow启用警告信息。影子变量将会在4.1节中进行讲解。警告信息有时是良性的,但是它们通常表明在代码中有深层的问题。总是启用警告信息并按照gcc的建议去做是一个好的习惯。输出文件(即可执行文件)的名字由-o所指定。在本例中,p1是此gcc命令的输出,因此是可执行文件(即程序)。它可以通过在终端中输入下列内容来运行:
screenshot
输出应该和下面相同:
screenshot
要看到调用栈,我们需要启动调试工具。在本例中,我们将使用DDD(命令行调试程序)。DDD是一个针对GDB调试工具的图形用户界面。启动DDD,进入菜单并点击:
File→Open Program→select p1→Open
这里,我们已经选择了可执行程序而不是.c文件。调试工具将自动地基于gcc留在可执行文件中的信息找到.c文件。当调试一个使用多个源文件的程序时这会很有用。
在底部窗口(gdb)提示之后,可在两个函数g1和g2中使用下面的指令设置断点:
screenshot
指令b g1指示DDD在函数g1开始时设置一个断点。当程序到达g1的第一行,程序将停止,你会有机会检查程序的状态。指令b g2指示DDD在函数g2开始时类似地去设置一个断点。
通过在(gdb)提示时输入下面的指令来执行此程序:
screenshot
程序将会启动,然后在函数g2的断点处停止。为什么程序在g2处停止而不是g1呢?因为main函数调用g2,所以g2在g1之前被执行。如果设置了多个断点,那么程序将按照它们被执行的顺序停止在断点处,而不是按照它们被设置的顺序。在本例中,虽然在g1中的断点是先设置的,但程序先执行g2。所以,程序将先停在g2中的断点处。
要继续这个程序,输入下面的指令:
screenshot
程序将继续执行,之后停在下一个断点处,该断点位于函数g1中。调用栈可以通过调用栈回溯查看到。这可以用下面的指令完成:
screenshot
这条指令的意思是“栈回溯”。你会在调试工具中看到什么?
screenshot
a和b的值在顶部栈帧中显示。每一行的起始显示了调用栈的栈帧(0、1和2),与函数g1、g2和main函数相对应。可以使用f命令来看到不同的栈帧:例如,输入:
screenshot
可以看到frame1,即函数g2的栈帧。a和b的值被再一次地显示。它们的值是多少呢?0x之后的数字在你的计算机上可能与此不同,这些就是地址。在g2的栈帧中,a和b的值与顶部栈帧中的值不同。图2.6~图2.9显示了一些DDD的截图。
screenshot
screenshot
screenshot
screenshot

原文标题:C语言程序设计进阶教程一2.7 在DDD(命令行调试程序)上检测调用栈

相关文章
|
1月前
|
存储 自然语言处理 编译器
【C语言】编译与链接:深入理解程序构建过程
【C语言】编译与链接:深入理解程序构建过程
|
1月前
|
C语言 开发者
C语言实现猜数字小游戏(详细教程)
C语言实现猜数字小游戏(详细教程)
|
1月前
|
编译器 C语言 C++
VSCode安装配置C语言(保姆级教程)
VSCode安装配置C语言(保姆级教程)
|
28天前
|
C语言
C语言调试
C语言调试
14 0
|
29天前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序
|
2月前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
2月前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第六章 数组_一维数组_二维数组_字符数组详解
本章介绍了C语言中的数组概念及应用。数组是一种存储同一类型数据的线性结构,通过下标访问元素。一维数组定义需指定长度,如`int a[10]`,并遵循命名规则。数组元素初始化可使用 `{}`,多余初值补0,少则随机。二维数组扩展了维度,定义形式为`int a[3][4]`,按行优先顺序存储。字符数组用于存储字符串,初始化时需添加结束符`\0`。此外,介绍了字符串处理函数,如`strcat()`、`strcpy()`、`strcmp()` 和 `strlen()`,用于拼接、复制、比较和计算字符串长度。
|
2月前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。