惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cisco Blogs
爱范儿
爱范儿
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
Jina AI
Jina AI
Project Zero
Project Zero
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
Simon Willison's Weblog
Simon Willison's Weblog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
F
Fortinet All Blogs
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
月光博客
月光博客
雷峰网
雷峰网
G
Google Developers Blog
V
V2EX
T
Tor Project blog
罗磊的独立博客
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
W
WeLiveSecurity
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Privacy International News Feed
S
Securelist
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
小众软件
小众软件
Scott Helme
Scott Helme
I
Intezer
T
Threat Research - Cisco Blogs
The GitHub Blog
The GitHub Blog
N
Netflix TechBlog - Medium
C
CERT Recently Published Vulnerability Notes
Security Archives - TechRepublic
Security Archives - TechRepublic
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LINUX DO - 最新话题
N
News | PayPal Newsroom
L
Lohrmann on Cybersecurity
T
Troy Hunt's Blog
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
人人都是产品经理
人人都是产品经理
Latest news
Latest news
AWS News Blog
AWS News Blog
Apple Machine Learning Research
Apple Machine Learning Research

喵's StackHarbor

学习 OpenGL 1 | 喵's StackHarbor Automata: A Story of Love and Lives | 喵's StackHarbor 在 VPS 上用 Nginx 和 HTTPS 部署 Hexo 生成的页面 | 喵's StackHarbor 无尽的咏叹回荡于伽蓝之世界中 —— 有关 ARIA | 喵's StackHarbor GitHub Pages 自定义域名启用 HTTPS(非 CloudFlare) | 喵's StackHarbor 写给新手的 Linux 手册 1 | 喵's StackHarbor Kalafina, My Music Life | 喵's StackHarbor コラージュ(卫宫家今天的饭 ED)曲谱 | 喵's StackHarbor CoffeeScript 的静态方法和静态变量(类方法和类变量) | 喵's StackHarbor StackHarbor的2017尾记 | 喵's StackHarbor - Whisper to the World 忧从中来,不可断绝 | 喵's StackHarbor - Whisper to the World 冬天来了 | 喵's StackHarbor - Whisper to the World 我生气了!!! | 喵's StackHarbor - Whisper to the World Be Brave | 喵's StackHarbor Dirty Words | 喵's StackHarbor 你的名字。 | 喵's StackHarbor - Whisper to the World Encrypted for the Update. | 喵's StackHarbor 突然更新 | 喵's StackHarbor - Whisper to the World 灰色情人节 | 喵's StackHarbor - Whisper to the World
使用GDB进行简单的C语言程序调试 | 喵's StackHarbor - Whisper to the World
2017-03-15 · via 喵's StackHarbor

事实证明有时候无聊的东西反而变成了一篇博文,谁叫恶趣味的C语言作业非要求用word写实验报告,本猹宁可先写成Markdown再复制粘贴过去。

首先按照惯例应该介绍下GDB,搭配GCC使用的调试器,也是众多使用GCC为编译器的IDE的默认调试器(大概?),虽然无聊的实验报告模板还很搞笑的写了一个部分叫XXX调试器和VC6.0的比较(看戏的内心:我看过两年学生出生时间比VC6还晚的时候这些课还怎么拿VC6讲)。

所以掌握GDB的使用还是很有必要的,毕竟掌握某个使用GDB的IDE终究只是掌握了一个图形壳子,原理估计还是要深入一层到直接用GDB(强行接入正经模式)。

这里只是按照实验报告的要求写一下断点调试和单步执行的用法(PS:Word实在是太难用了,字号缩进和标题序号就没有按照我想要的方式工作过。


准备

调试模式编译程序

首先应该明确调试的实现方式,GDB能够暂时的停下程序操作程序其实是通过向编译过程中的二进制流中添加钩子(HOOKS)来实现的。但是对于一个正常的,打算释出给用户使用的程序而言不应该以调试模式编译,因为这些添加进去的钩子不但会增大文件体积,还会降低程序的运行效率。所以GCC默认编译程序的时候时不会添加这个钩子的,需要的时候以-g参数来启用调试模式。

本例中以文件Lab2.c为例,使用命令

1
$ gcc -std=c11 -g -o lab Lab2.c

将它编译到可执行文件lab。

打开程序的命令很简单,就是$ gdb lab,但是有可能遇到的问题是程序要处理命令行参数,在使用GDB的时候是不能直接在命令行后面附加程序参数的,需要使用参数可以在打开GDB之后输入set args 参数1 参数2 ...附加上参数。

用GDB打开程序之后是一个交互界面,显示了一些信息和(gdb)这个提示符,表示你现在是在和GDB进行交互而不是程序。这个时候程序是不会运行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GNU gdb (GDB) 7.12.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from lab...done.
(gdb)

调试

设置断点

首先使用break指令就可以添加一个断点,断点顾名思义就是程序运行到这个位置会暂停下来交给GDB,这样你才能够在程序运行到一半的时候查看一些可疑的变量,断点是针对函数使用的,比如我想在所有的printf()进入的时候暂停,可以使用:

1
(gdb) break printf

显示的是这样的:

1
2
(gdb) break printf
Breakpoint 1 at 0x400540

当然接下来可以继续添加更多的断点。

然后使用run就可以让程序跑起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(gdb) run
Starting program: /home/alynx/Homework/实验材料(学生版)/实验2/lab
[实验2说明]本练习运行一个三重for循环, 循环结构如下:
int count = 0;
for(int i=0; j<LoopEnd1; i++)
{
//第一重循环体
for(int j=0; j<LoopEnd2; j++)
{
//第二重循环体
for(int s=0; s<LoopEnd3; s++)
{
count++;//第三重循环体
}
}
}

Breakpoint 1, 0x00007ffff7a86e00 in printf () from /usr/lib/libc.so.6

这时候使用print指令可以打印任意的内容:

1
2
(gdb) print printf
$1 = {<text variable, no debug info>} 0x7ffff7a86e00 <printf>

使用bt指令可以显示出程序的栈(Backtrace):

1
2
3
(gdb) bt
#0 0x00007ffff7a86e00 in printf () from /usr/lib/libc.so.6
#1 0x0000000000400745 in main (argc=1, argv=0x7fffffffe078) at Lab2.c:26

输入c就是继续运行程序的意思。但是step指令的功能更加有用,顾名思义这个就是单步运行,每次只运行一行代码,这是个step-in的模式,即如果该行有函数则进入函数内一行一行运行,而next则是step-over的模式,即如果该行有函数会运行函数返回结果而不是进入函数内部。

1
2
3
4
5
(gdb) step
Single stepping until exit from function printf,
which has no line number information.
main (argc=1, argv=0x7fffffffe078) at Lab2.c:27
27 scanf("%d", &LoopEnd1);

如果不输入指令直接回车,就是重复上一条指令,程序运行结束之后可以使用quit指令退出GDB。


好了本猹要去补作业了。

AlynxZhou

A Coder & Dreamer