# gdb选项命令

  • 快捷键,command+shift+L
<font style="background:yellow">
<font style="background:pink">
<font style="background: MediumSpringGreen">
1
2
3

我们约定(gdb) 命令,表示该命令在gdb里面调试的意思,不是在bash中运行

有人说:厉害的调试需要比开发付出2倍以上的努力

  • gdb设计哲学

1.gdb里面也能用Tab来补全

2.gdb中使用(gdb) help可以查看各种内置gdb命令语法

3.退出gdb使用(gdb) q就行了 「或快捷键Ctrl+d

# 目录

[TOC]

# 1.gdb历史发展

​ gdb是由gnu 软件系统社区提供的调试工具,注意的,它是调试程序的一个工具。那么这个gdb 啊同我们之前啊所学习的这个gcc 啊编译套件。那么他们呢配套啊组成了一套完整的开发环境啊

​ gdb 呢它是linux 啊和许多这个类unix系统当中啊,它的一个标准的开发环境。一般来说呢,这个gdb 啊这个调试工具啊主要能够帮助你完成下面四个方面的功能啊。

  • 1.启动程序,可以按照自定义的要求随心所欲的运行程序

  • 2.可让被调试的程序在所指定的调置的断点处停住(断点可以是条件表达式)

  • 3.当程序被停住时,可以检查此时程序中所发生的事

    • 比如说呢我想看一个这个变量,它的值是什么
  • 4.可以改变程序,将一个BUG产生的影响修正,从而测试其他 BUG

​ 就是当我们用这个GDB啊去调试的时候啊,比如说我们发现了一个bug 了,对吧?其实我们是可以把这个程序啊。啊,修改过来了,就通过GDB 的一些指令啊,比如说我设置某个变量,把它的值呢给⭐️设置正确了⭐️。那么接下来呢我们就可以继续往下去测试其他的这个bug 了。对吧,如果说你第一个bug 没有啊,这个呃结果呢是错误的,那你后面这个bug 其实他测出来的这个意义啊,有的时候呢是没有任何意义的,对吧?

  • 可能bug 和bug 之间呢会有这个相互的一个影响—依赖关系。

​ GDB 啊,它的一个吉祥物啊,那这个吉祥物它是一条鱼,对吧?他不是普通的鱼,它是一个什么呢?射手鱼,大家都知道他可以去往这个外面呢去吐这个水泡,对吧?吐水啊,那么呃他呢能够把这个树上的虫子。通过这个水呢给击落下来啊,来去捕捉这个虫子嘛,对吧?那么虫子是什么呀,虫子是不是就是bug 呀,对吧?所以说他的这个吉祥物啊还是啊非常有这个意思的,对吧?啊,非常的这个形象啊,我通过这个鱼去吐水啊,把这个树上的bug 呢给击落下来啊,其实就是去找bug 啊,那这样呢大家了解一下。

​ 然后呢,我们来看一下,我们要进行这个g d b 调试啊,我们需要做的一些⭐️准备工作。那么通常呢在为调试而编译时,我们会干嘛呢?

  • 1.通常,在为调试而编译时,我们会⭐️关掉编译器的优化选项(-O),并打开调试选项(-g)

    • 关掉这个啊编译器的一个优化选项⭐️啊,就是-大O的参数,那其实⭐️你不关的话也没有关系⭐️啊
    • 加上一个-g参数啊,那具体怎么操作呢?比如说啊gcc -g,对吧?==-g你放在前面,放在后面都无所谓==。
  • 2.另外, -Wall在尽量不影响程序行为的情况下选项打开所有warning,也可以发现许多问题,避免一些不必要的 BUG。因为有的时候呢,这个警告它其实也是这个问题,对吧?也是这个bug 啊,也可以发现许多问题,避免一些不必要的bug。

    • gcc -g -Wall program.c -o program
    • 然后-Wall打开这个所有的警告,这个你不加的话呢也没有关系啊
    • -g选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并⭐️不是把整个源文件嵌入到可执行文件中,所以⭐️在调试时必须保证gdb能找到源文件(意思是:源码的路径和可执行文件之间的相对位置要不变)

==注意了,他不是把原文件的代码就直接嵌入到这个可执行程序当中了==。他只是把这些啊,比如说你这个可执行程序,它里面的代码,对吧?二进制的这个代码吗?对吧?比如说对应的是我们源代码的。第几行啊,那么他会把这些信息打包到这个可执行程序当中啊,所以呢我们在调用这个就是说在调试这个程序的时候啊,你必须要保证这个gdb啊能够找到原文件。==如果说找不到的话,那它就不能进行一个断点调试啊==,他就不能通过这个gdB去调试。

# 2.基础命令

# 2.1.开启TUI模式的GDB

方法1:

gdb test -tui
1

方法2:

​ 在GDB中使用Ctrl+X+A快捷键,切换TUI模型

  • 版本6.1以来,GDB以名为TUI(Terminal User Interface,终端用户界面)的模式提供了基于文本交互和图形用户交互之间的折中方法

# 2.2.设置参考-查看具体代码

意义 启动和退出 示例
启动gdb gdb 可执行程序 gdb a.out
退出gdb q/quit (gdb) q
给程序设置参数 (gdb) set args 10 20
获取程序的设置参数 (gdb) show args
列出gdb的所有命令使用帮助 (gdb) help
获取某条gdb命令具体的帮助文档 (gdb) help set args
查看当前文件代码(从默认位置显示) l/list (gdb) l
查看当前文件代码(从指定的行显示,显示该行的上下文)「注意,这是以该为中间的哪部分显示,而不是从该行开始显示的」 l 行号 (gdb) l 13
查看当前文件代码(从指定的函数显示,显示该函数的上下文) l 函数名 (gdb) l func
查看非当前文件代码「看其他代码的文件」 list/ l文件名:行号 (gdb) l pragma.c:13
list/ l文件名:函数名 (gdb) l pragma.c:alignof
查看显示的行数 show list/ listsize
设置显示的行数 set list/ listsize行数

# 2.3.断点操作(增+删+改+查看)

​ 「break point」设置断点

意义 命令
在本文件的某行设置断点 (gdb) b 13
在某个函数名设置断点:大型调试常用 (gdb) b main
(gdb) b prgama.cpp:cgmain
在某文件的某行,断点 (gdb) b main.cpp:31
查看所有断点 (gdb) info break
删除断点 (gdb) d 断点编号
设置断点无效「disable」 (gdb) dis/ disable 断点编号
设置断点生效(使能断点)「enable」 (gdb) ena/enable断点编号
设置条件断点(一般用在循环的位置) (gdb) b 10 if i==5
正则表达式的断点,rbreak 可以跟一个规则表达式。rbreak + 表达式的用法与grep + 表达式相似。即在所有与表达式匹配的函数入口都设置断点 rbreak list_*即在所有以 list_ 为开头字符的函数地方都设置断点
  • info program: 来查看程序的是否在运行,进程号,被暂停的原因。
(gdb) info program
	Using the running image of child process 11013.
Program stopped at 0xaaaaaabcbd48.
It stopped after being stepped.
Type "info stack" or "info registers" for more information.
1
2
3
4
5

# 2.4.调试命令

意义 命令
在GDB里面运行程序,程序停在第一行 (gdb) start
在GDB里面运行程序,遇到断点才停 (gdb) run
继续运行,到==下一个断点==停 (gdb) c/continue
向下执行一行、多行代码(不会进入函数体 (gdb) n
(gdb) n 3
「函数相关」⭐️向下单步调试,遇到函数进入函数体 (gdb) s/step
「函数相关」执行完当前函数,==跳出函数体== (gdb) finish
「循环相关」⭐️跳出循环 (gdb) until
「手动,临时修正bug」⭐️ (gdb) set var 变量名=变量值 (循环中用的较多)

变量操作

  • p/print 变量名(打印变量值)
  • ptype 变量名(打印变量类型)

自动变量操作

  • display 变量名(自动打印指定变量的值)
  • i/info display
  • undisplay 编号

# 2.6.窗口看汇编—layout模式使用

意思 命令
⭐️使能TUI模式「enable」 (gdb) tui enable
layout 命令用于分割窗口,可以一边查看代码,一边测试
显示源代码⭐️窗口 (gdb) layout src
显示汇编⭐️窗口 (gdb) layout asm
显示源代码/汇编和寄存器⭐️窗口 (gdb) layout regs
显示源代码和汇编窗口 ⭐️ (gdb) layout split
⭐️退出TUI模式或者layout模式「disable」 (gdb) tui disable
(gdb) layout next:显示下一个layout
(gdb) layout prev:显示上一个layout

(gdb) Ctrl + L:刷新窗口	⭐️
(gdb) Ctrl + x,再按1:单窗口模式,显示一个窗口
(gdb) Ctrl + x,再按2:双窗口模式,显示两个窗口
(gdb) Ctrl + x,再按a:回到传统模式,即退出layout,回到执行layout之前的调试窗口
1
2
3
4
5
6
7

​ 这样有个弊端,开了两个窗口不能上下切换查看历史命令,怎么解决

​ ⭐️使用fs next命令「类似Windows下切换窗口快捷键」切换窗口焦点「在unbuntu的Linux下,我们发现,某个窗口,他的四边形框框是蓝色

  • 比如下面的使用,这样的话,我的翻页就能对src源码翻页,而不是gdb的历史命令翻页
(gdb) fs next   
Focus set to cmd⭐️ window.
(gdb) fs next 
Focus set to src⭐️ window.
1
2
3
4

# 2.6.gdb调试汇编指令⭐️

作用 举例
⭐️汇编单步,也可使用s一次执行多条指令(取决于C源码),si执行一条汇编指令 (gdb) si
⭐️给寄存器赋值 (gdb) set $x1=85
⭐️强行终止调试程序 (gdb) kill
监视变量var_a (gdb) watch var_a
打印所有寄存器的值 (gdb) info registers
⭐️直接查看这个内存地址存放的内容 (gdb) x 0xc0000000018ac130
设置硬件断点(hardware breakpoint) (gdb) hb boot_cpu_init
⭐️print,打印$x1寄存器的值,p后面加'x'表示16进制 (gdb) p/x $x1
打印变量内存地址 (gdb) p &vara
查看内存变量vara的值,赋值语法同寄存器赋值 (gdb) p vara
用16进制的方式打印相应的32位 (gdb) p/x cur-num
⭐️查看寄存器 (gdb) info register
⭐️查看具体寄存器【注意,不需要%eax】 (gdb) info register eax
反汇编函数 (gdb) disassemble main
disaseembit 汇编
built-in的函数直接转为指令了


GDB默认汇编格式是AT&T格式,windows用户会感觉很蛋疼,GDB很给力的支持切换成intel指令集。

切换intel格式的命令:
set disassembly-flavor intel

切换成att格式的命令:
set disassembly-flavor att

举例
(gdb) set disassembly-flavor intel
(gdb) disassemble /m addme
Dump of assembler code for function addme:  带源码的反汇编addme函数
(gdb) disassemble main 反汇编main函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

区分,硬件断点、软件断点、内存断点

# 2.7.gdb内执行shell指令

用特殊符号!开头.
好处就是可以边调试边看源码,甚至进行一些其他操作.
!vim demo.cpp
!pwd
#查看进来时的工作目录.
1
2
3
4
5

# 2.8.函数调用栈

​ 下面是一些查看函数调用栈信息的GDB命令, 如在遇到段错误时,输入bt命令,即可跟踪错误,非常好用,方便记忆。可以叫变态

意义 命令
bt打印当前的函数调用栈(backtrace)的所有信息, (gdb) bt
frame

# 3.调试多进程or多线程⭐️

​ 多进程和多线程调试,是后台程序调试⭐️不可避免⭐️而又比较困难的部分

# 3.1.调试-多进程

​ 如果一个进程通过fork系统调用创建了子进程,『gdb 会继续调试原来的进程,子进程则正常运行』

​ 那么该如何调试子进程呢? 常用的方法有如下两种。比如,『子进程从本质上说也是一个进程』,因此我们可以用通用的gdb调试方法来调试它。

ps -ef | grep 服务器程序名
1

​ 我们可以先运行服务器,然后找到目标子进程的PID,再将其附加(attach)到gdb调试器上。

​ 注意,和平常不一样了,需要指定跟踪父进程还是子进程?可以在fork函数调用之前(注意,一定要在fork函数调用之前设置才有效),通过指令设置gdb调试工具跟踪父进程或者是跟踪子进程。如果不设置,则默认跟踪父进程(使用gdb调试的时候,gdb只能跟踪一个进程。)

意义 命令
选定某进程PID,进行调试 attach 4183
设置跟踪父进程 set follow-fork-mode parent
命令设置gdb在fork之后跟踪子进程 set follow-fork-mode child
  • 问:要是有多个子进程,怎么办?可以设置断点,条件断点

# 3.2.调试-多线程thread

​ gdb有一组命令可辅助多线程程序的调试。下面我们仅列举其中常用的一些:

意义 举例
⭐️调试目标ID指定的线程 (gdb) thread 3
显示当前可调试的所有线程 (gdb) info threads

​ 关于调试进程池和线程池程序的一个不错的方法,是先将池中的进程个数或线程个数减少至1,以观察程序的逻辑是否正确,然后逐步增加进程或线程的数量,以调试进程或线程的『同步』是否正确。

  • Info threads的结果:gdb会为每个线程分配一个ID,我们可以使用这个ID来操作对应的线程。ID前面有“*”号的线程是当前被调试的线程。

调试多线程程序时,默认除了被调试的线程在执行外,其他线程也在继续执行,但有的时候我们希望只让被调试的线程运行。这可以通过这个命令来实现。该命令设置scheduler-locking 的值:

  • set scheduler-locking [ off | on | step ]
    • off表示不锁定任何线程,即所有线程都可以继续执行,这是默认值;
    • on表示只有当前被调试的线程会继续执行﹔
    • step表示在单步执行的时候,只有当前线程会执行。

# 4.场景1-编译器开发⭐️

# 4.1.gdb调试gcc的坑⭐️

直接gdb那个生成的gcc是调试gcc的driver

  • gcc 二进制文件实际上是一个相对较小的“驱动(driver)”程序,它解析一些命令行选项,然后调用一个或多个其他程序来完成真正的工作

使用这个才是调试ccl⭐️

  • 用这条指令就可以了
  • 好像直接gdb gcc调试的是gcc driver
  • -wrapper gdb,--args 调试的是真实的编译器cc1
gcc test.c  -S -Os -wrapper gdb,--args
1

坑点:gdb,--args必须紧挨着写

XXX@XXX:~/debug_test$ gcc -wrapper gdb, --args whoway.c
gcc: error: unrecognized command line option '--args'
XXX@XXX:~/debug_test$ gcc -wrapper gdb,--args whoway.c
这样才可以
1
2
3
4

gdb这样使用后(不需要set args或者r的时候添加参数了)✔️

  • 直接run就行了
  • 记得,调试ccl的时候,不能加-S
whoway@XXXX:~/debug_test$ gcc -Os -fldm-stm-optimize test.c -wrapper gdb,--args
1

# 4.2.最新组会调试hcc-2022.5.7⭐️

# 4.2.1.解决-构造hcc可调式版-失败的原因!✔️

# 步骤
  • 1.修改build_toolchain.sh

全部替换下面的

:%s/-Os/-g -O0/g
:%s/-O2/-g -O0/g
1
2
  • 2.然后更新编译(./build_toolchain.sh update)> tee 2>&1(还是无法找到debug信息,失败)⛔️
  • 3.==完全重新编译hcc_riscv32==,也就是(./build_toolchain.sh hcc_riscv32)>tee 2>&1(成功✔️)

关注细节

# 调试hcc使用公版gdb而不是riscv_gdb
  • 使用==gdb==而不是riscv_gdb

  • 重新编译

gdb XXXXX/cc1 
(gdb)先break然后再测试
(gdb)r lli2.c
(gdb)进行东西

__builtin_clz
1
2
3
4
5
6
# 调试命令展示⭐️
  • 调试cc1而不是drive
gdb /home/whoway/work/hcc_riscv_gcc/output/hcc_riscv32/libexec/gcc/riscv32-unknown-elf/7.3.0/cc1

1
2
  • 断点
b riscv_judge_and2shift_continuous_bits(unsigned int, int)
1
  • 这样才能,运行测试样例
r lli-and2shift-insn2.c -Os -mlli-expand -mand-shift-opt -femit-lli 
1
  • 小提示:不能-c,虽然你没有main函数,不然报错⭐️
cc1: error: command line option '-c' is valid for the driver⭐️ but not for C

cc1:错误:命令行选项“-c”对驱动程序⭐️有效,但对 C 无效
1
2
3
# 直接调试cc1
whoway@job:~/execute$ gdb /home/whoway/work/hcc_riscv_gcc/output/hcc_riscv32/libexec/gcc/riscv32-unknown-elf/7.3.0/cc1	✔️
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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-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 /home/whoway/work/hcc_riscv_gcc/output/hcc_riscv32/libexec/gcc/riscv32-unknown-elf/7.3.0/cc1...
(gdb) l
21	#include "system.h"
22	#include "coretypes.h"
23	#include "tm.h"
24	#include "diagnostic-core.h"
25	#include "toplev.h"
26	
27	int main (int argc, char **argv);
28	
29	/* We define main() to call toplev::main(), which is defined in toplev.c.
30	   We do this in a separate file in order to allow the language front-end
(gdb) r lli-and2shift-insn2.c
Starting program: /home/whoway/work/hcc_riscv_gcc/output/hcc_riscv32/libexec/gcc/riscv32-unknown-elf/7.3.0/cc1 lli-and2shift-insn2.c
 test
Analyzing compilation unit
Performing interprocedural optimizations
 <*free_lang_data> <visibility> <build_ssa_passes> <opt_local_passes> <targetclone> <free-inline-summary> <whole-program> <inline>Assembling functions:
 <materialize-all-clones> test
Execution times (seconds)
 phase setup             :   0.01 (50%) usr   0.00 ( 0%) sys   0.06 (35%) wall     923 kB (85%) ggc
 phase parsing           :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.02 (12%) wall     101 kB ( 9%) ggc
 phase opt and generate  :   0.01 (50%) usr   0.00 ( 0%) sys   0.09 (53%) wall      50 kB ( 5%) ggc
 callgraph construction  :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.02 (12%) wall       0 kB ( 0%) ggc
 parser function body    :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.02 (12%) wall       5 kB ( 1%) ggc
 tree gimplify           :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.02 (12%) wall       2 kB ( 0%) ggc
 expand                  :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.03 (18%) wall       3 kB ( 0%) ggc
 integrated RA           :   0.01 (50%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall      24 kB ( 2%) ggc
 LRA non-specific        :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.01 ( 6%) wall       0 kB ( 0%) ggc
 initialize rtl          :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.01 ( 6%) wall       7 kB ( 1%) ggc
 TOTAL                 :   0.02             0.01             0.17               1083 kB
[Inferior 1 (process 2768299) exited normally]
(gdb) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# 4.2.2.调试函数

  • riscv_judge_and2shift_continuous_bits
⭐️r lli-and2shift-insn2.c -Os -mlli-expand -mand-shift-opt -femit-lli
1
(gdb) b riscv_judge_and2shift_continuous_bits(unsigned int, int)
1
  • 虽然lli-and.2.c是编译的
(gdb) r lli-and2shift-insn2.c -c⭐️ -Os -mlli-expand -mand-shift-opt -femit-lli
Starting program: /home/whoway/work/hcc_riscv_gcc/output/hcc_riscv32/libexec/gcc/riscv32-unknown-elf/7.3.0/cc1 lli-and2shift-insn2.c -c -Os -mlli-expand -mand-shift-opt -femit-lli
cc1: error: command line option '-c' ⭐️is valid for the driver but not for C

Execution times (seconds)
 TOTAL                 :   0.00             0.00             0.00                  8 kB
[Inferior 1 (process 2785637) exited with code 01]

⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
(gdb) r lli-and2shift-insn2.c -Os -mlli-expand -mand-shift-opt -femit-lli
Starting program: /home/whoway/work/hcc_riscv_gcc/output/hcc_riscv32/libexec/gcc/riscv32-unknown-elf/7.3.0/cc1 lli-and2shift-insn2.c -Os -mlli-expand -mand-shift-opt -femit-lli
 test
Analyzing compilation unit
Performing interprocedural optimizations
 <*free_lang_data> <visibility> <build_ssa_passes> <opt_local_passes> <targetclone> <free-inline-summary> <whole-program> <profile_estimate> <icf> <devirt> <cp> <inline> <pure-const> <static-var> <single-use> <comdats>Assembling functions:
 <materialize-all-clones> test
Breakpoint 1, riscv_judge_and2shift_continuous_bits (cur_num=32767, select_mode=-139277408)
    at /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/predict.c:3819
3819	{
(gdb) disp
(gdb) p select_mode 
$1 = -139277408

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
whoway@job:~/execute$ cat lli-and2shift-insn2.c

int test(int a, int b)
{
        int c = b & 0x7fffffff;
        return a + c;
}
1
2
3
4
5
6
7
  • step后cur_num就变化了?
  • 2147483647
  • p select_mode 1
‭0111	1111	1111	1111	1111	1111	1111	1111
1
(gdb) b /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/config/riscv/peephole.md:201
Breakpoint 2 at 0xf2fd11: /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/config/riscv/peephole.md:201. (2 locations)
(gdb) b /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/config/riscv/peephole.md:200
Breakpoint 3 at 0xf61348: file /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/config/riscv/peephole.md, line 200.
(gdb) b /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/config/riscv/peephole.md:202
Breakpoint 4 at 0xf6138d: file /home/whoway/work/hcc_riscv_gcc/open_source/gcc-7.3.0/gcc/config/riscv/peephole.md, line 202.

1
2
3
4
5
6
7

# 4.2.3.汇编-peephole2.md

whoway@job:~/execute$ riscv32-unknown-elf-objdump -d lli-and2shift-insn2.o

lli-and2shift-insn2.o:     file format elf32-littleriscv


Disassembly of section .text:

00000000 <test>:
   0:	800007b7          	lui	a5,0x80000
   4:	fff7c793          	not	a5,a5
   8:	8dfd                	and	a1,a1,a5
   a:	952e                	add	a0,a0,a1
   c:	8082                	ret

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 5.场景2-调试openmp

step 1:gdb test_omp

step 2:break 15

step 3:run

gdb) info threads
  4 Thread 0x7ffff640d700 (LWP 17110)  main.omp_fn.0 (.omp_data_i=0x7fffffffe3b0) at test_omp.c:15
  3 Thread 0x7ffff6c0e700 (LWP 17109)  main.omp_fn.0 (.omp_data_i=0x7fffffffe3b0) at test_omp.c:15
  2 Thread 0x7ffff740f700 (LWP 17108)  main.omp_fn.0 (.omp_data_i=0x7fffffffe3b0) at test_omp.c:15
* 1 Thread 0x7ffff7fdf780 (LWP 17105)  main.omp_fn.0 (.omp_data_i=0x7fffffffe3b0) at test_omp.c:15

1
2
3
4
5
6
7
8
9
10
11
12

bt命令

​ 对于当前调试环境中存在的栈帧,GDB 调试器会按照既定规则对它们进行编号:当前正被调用函数对应的栈帧的编号为 0调用它的函数对应栈帧的编号为 1以此类推

(gdb) bt
#0  __kmpc_fork_call (loc=0x20000ffff, argc=0, microtask=0x0)
    at /home/whoway/big-benchmark/classic-flang-llvm-project/openmp/runtime/src/kmp_csupport.cpp:262
#1  0x00000000004012f9 in main::testfirstprivate () at private.f95:13
#2  0x000000000040129c in main () at private.f95:8
#3  0x00000000004014fe in main (argc=1, argv=0x7fffffffc4b8)
    at /home/whoway/big-benchmark/kmpl-flang/runtime/flangmain/flangmain.c:59
(gdb) !vim private.f95
(gdb) frame 0
#0  __kmpc_fork_call (loc=0x20000ffff, argc=0, microtask=0x0)
    at /home/whoway/big-benchmark/classic-flang-llvm-project/openmp/runtime/src/kmp_csupport.cpp:262
262	void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro microtask, ...) {
(gdb) frame 1
#1  0x00000000004012f9 in main::testfirstprivate () at private.f95:13
13	      !$omp parallel firstprivate(atest)
(gdb) frame 2
#2  0x000000000040129c in main () at private.f95:8
8		call testfirstprivate()
(gdb) frame 3
#3  0x00000000004014fe in main (argc=1, argv=0x7fffffffc4b8)
    at /home/whoway/big-benchmark/kmpl-flang/runtime/flangmain/flangmain.c:59
59	  MAIN_(argc, argv, __io_environ());
(gdb) bt
#0  __kmpc_fork_call (loc=0x20000ffff, argc=0, microtask=0x0)
    at /home/whoway/big-benchmark/classic-flang-llvm-project/openmp/runtime/src/kmp_csupport.cpp:262
#1  0x00000000004012f9 in main::testfirstprivate () at private.f95:13
#2  0x000000000040129c in main () at private.f95:8
#3  0x00000000004014fe in main (argc=1, argv=0x7fffffffc4b8)
    at /home/whoway/big-benchmark/kmpl-flang/runtime/flangmain/flangmain.c:59
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 6.其他细节

# 6.1.导入符号表file✔️

file

  • 导入符号表,其实gdb进来,要是读取成功了,就不用这个了
(gdb) file a.out 
Load new symbol table from "a.out"? (y or n) y
Reading symbols from a.out...
1
2
3

# 6.2.load✔️

load好像可以在调试的时候,换执行文件,具体参考下面

whoway@XXX:~/solvelbu/riscv_gcc/output/riscv32/bin$ ./gdb gcc
GNU gdb (GDB) 10.1
Copyright (C) 2020 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 "--host=x86_64-pc-linux-gnu --target=riscv32-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://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"...

warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB.  Attempting to continue with the default riscv settings.

Reading symbols from rgcc...
(No debugging symbols found in gcc)		#注意,这里没有读入“符号表”信息

(gdb) target sim
Connected to the simulator.
(gdb) load test
test    test.c  
(gdb) load test
Loading section .text, size 0xc0ee lma 0x10074
Loading section .rodata, size 0x10cc lma 0x1c168
Loading section .eh_frame, size 0x40 lma 0x1e234
Loading section .init_array, size 0x8 lma 0x1e274
Loading section .fini_array, size 0x4 lma 0x1e27c
Loading section .data, size 0x99c lma 0x1e280
Loading section .sdata, size 0x2c lma 0x1ec20
Start address 0x10084
Transfer rate: 450160 bits in <1 sec.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 6.3.常见问题

(gdb) b ira.c:ira
No source file named ira.c.
Make breakpoint pending on future shared library load? (y or [n]) n
1
2
3

出现上述,可能2种情况

  • 1.编译文件的时候,没加-g
  • 2.可能是比如gcc那样,不是调试的cc1
  • 3.b只能加在可能执行到的地方,riscv.md好像不行==(待考察)==

# 6.4.细节

(gdb) b regcprop.c:ldm_stm_replace_p(rtx_insn const*, rtx, rtx) 
Function "ldm_stm_replace_p(rtx_insn const*, rtx, rtx)" not defined in "regcprop.c".
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) b regcprop.c:ldm_stm_replace_p
Breakpoint 1 at 0x5a39c0: file /home/whoway/solvelbu/gcc/open_source/gcc-7.3.0/gcc/regcprop.c, line 487.
1
2
3
4
5

# 7.场景3-gdb的远程调试

# 7.1.组会调试经验(gdb+gdbserver远程调试技术)✔️

参考自@Wilson2334 (opens new window)的总结

  • 第1个bash用qemu开启端口1234「使用beta-qemu用户态加载程序」

    /home/XXX/buildroot_new/buildroot/output/host/bin/qemu-beta -g 8848 test.exe 
    
    1

    (此时该终端处于执行状态...)

  • 第2个bash用gdb调试,在gdb运行起来的时候,在里面开启端口「新建终端使用beta-gdb远程连接qemu」

  • 先加载程序

    /home/XXX/buildroot_new/buildroot/output/host/bin/beta-linux-gdb test.exe 
    
    1
  • 然后使用remote连接端口

    Reading symbols from test.exe...
    (gdb) target remote :8848
    Remote debugging using :8848
    _start () at ../sysdeps/beta/start.S:50
    50              call  load_gp
    (gdb) b main
    Breakpoint 1 at 0x1004e0: file flw_fsw_fadds_fsubs.c, line 10.
    (gdb) print a
    $1 = 1.01999998
    (gdb) l
    6       int main()
    7       {
    8           float a, b, res_add, res_sub;
    9
    10          a = 1.02;
    11          b = 2.01;
    12          foo();
    13          return 0;
    14      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  • 补充资料:gdb+gdbserver远程调试技术 (opens new window)

    • gdbserver在目标系统中运行,gdb则在宿主机上运行

# 7.2.gdb使用模拟器(免除远程调试)✔️

# 代码调试-无qemu的情况

  • 在riscv版本的gdb中使用target sim来进行
(gdb) b gcc-main.c:43
Breakpoint 1 at 0x1d7b7: file /home/whoway/solvelbu/gcc/open_source/gcc-/gcc/gcc-main.c, line 43.
(gdb) run
Don't know how to run.  Try "help target".
(gdb) target sim		#gdb特有的功能?
Connected to the simulator.
(gdb) run
Starting program: /home/whoway/solvelbu/gcc/output/riscv32/bin/gcc 
warning: No program loaded.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1d7b7
1
2
3
4
5
6
7
8
9
10
11
12

# ⭐️”牛客网“gdb演示「笔记」

# 1.演示开始

​ 那接下来我们去执行这个gdb,那么怎么去打开gdb呢?非常简单,执行一个gdb的这个==shell命令==。注意,这个gdb是个shell命令,后面呢跟上我们要执行的可执行文件啊,它的一个名称。

​ 好,回车好了,你看现在他是不是就切换成这个gdb了。对吧,就进入到gdb 里面了啊,注意了,那现在进入到gdb 里面以后啊,==他并没有把这个test 这个可执行程序啊运行起来啊==。一会呢我们还要通过其他的这个啊,指令呢去运行我们的这个程序啊。

​ 好,那么现在呢已经进入到这个gdb里面的,对吧?gdb里面哈,然后呢再给大家去介绍几个这个命令啊,那一个呢是给这个程序啊设置参数啊,以及呢获取这个设置的参数啊。那有的时候呢我们去呃执行这个。 ​ 可听程序啊,是不是会在后面加入一些参数啊啊我们来看一下,

# 2.set args和show args的实验

​ 所以呢我们在这个gdp 调试的时候呢,也可以给这个可执行程序啊设置一些传入的参数。

​ 那怎么设置呢?简单啊。一个是set at a r g s,然后后面是参数的这个值啊,那这个多个参数呢重新用空格呢隔开。好,那我们来设置一下。that 比如说ar gs 对吧?设置这个参数十。二十回撤啊,现在呢就设置起来了啊,那么一会我们去运行我们的这个可进程序的时候啊啊那么他是不是会把这个参数就传递给。我们这个可进程序里面的这个慢函数啊,对不对?

$ gdb test.exe
GNU gdb (GDB) 7.8.1
Copyright (C) 2014 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-w64-mingw32".
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 test.exe...done.
(gdb) set args 10 20			⭐️
(gdb) show args
Argument list to give program being debugged when it is started is "10 20".	⭐️
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

好,那么怎么去啊获取我们设置的参数呢?其实就是show args. 这个g d b。他是什么?他是一个shell命令

# 3.如果test没有使用-g生成,我们的gdb表现

  • test1是没有-g
  • test是有-g
whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ gdb test1.exe
GNU gdb (GDB) 7.8.1
Copyright (C) 2014 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-w64-mingw32".
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 test1.exe...done.		⭐️⭐️(其实这里会显示no debug symbols啥的)
(gdb) list
1       C:/crossdev/src/mingw-w64-v3-git/mingw-w64-crt/crt/crtexe.c: No such file or directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

​ 上面的,在高版本还会显示:大家注意看啊,我现在呢要去查看这个啊代码了,我们用一个list 指令啊回车,大家看一下他说什么,他说没有符号表被读取

  • test
whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ gdb test.exe
GNU gdb (GDB) 7.8.1
Copyright (C) 2014 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-w64-mingw32".
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 test.exe...done.
(gdb) list
1       #include <stdio.h>
2       #include <stdlib.h>
3
4       int test(int a);
5
6       int main(int argc, char* argv[]) {
7           int a, b;
8           printf("argc = %d\n", argc);
9
10          if(argc < 3) {

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# ⭐️观察:不要移动你的源码位置,我移动了源文件位置,就算你-g也没用

whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ ls
 bubble.cpp    main.cpp     sort.h   test.exe*    手链.md
 desktop.ini   select.cpp   test.c   test1.exe*  '新建 DOCX 文档.docx'

whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ mkdir temp

whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ gdb test.exe
GNU gdb (GDB) 7.8.1
Copyright (C) 2014 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-w64-mingw32".
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 test.exe...done.
(gdb) l	⭐️⭐️
1       #include <stdio.h>
2       #include <stdlib.h>
3
4       int test(int a);
5
6       int main(int argc, char* argv[]) {
7           int a, b;
8           printf("argc = %d\n", argc);
9
10          if(argc < 3) {
(gdb) q

whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ mv test.c  temp/	⭐️⭐️

whoway@LAPTOP-DI85I9OS MINGW64 ~/Desktop
$ gdb test.exe
GNU gdb (GDB) 7.8.1
Copyright (C) 2014 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-w64-mingw32".
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 test.exe...done.
(gdb) l
1       test.c: No such file or directory.	⭐️⭐️(注意点!!!注意,调试的时候,你的源代码文件也要和我们的可执行文件在一起)
(gdb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  • ⭐️⭐️(注意点!注意,调试的时候,你的源代码文件也要和我们的可执行文件在一起)

# 多次list可能显示代码

​ 在gdb中,那么这个地方呢大家注意了,==如果说我啥,不输入按回车啊,默认呢它是继续去啊使用上一次的命令,==上一次的命令呢就是这个list。

​ 啊,因为这个是什么点cpu 文件是吧?那我们说一般呢用这个记忆佳佳呢去编译点c pp 文件啊==,如果你用gcc 去编译的话呢,它其实。找不到这个c 加加的一些库。==

# 演示

whoway@ubuntu:~/nowcoder$ ls
bubble.cpp  main.cpp  select.cpp  sort.h  test.c
whoway@ubuntu:~/nowcoder$ gcc bubble.cpp main.cpp select.cpp -o main -g
/usr/bin/ld: /tmp/ccfmeEhF.o: in function `__static_initialization_and_destruction_0(int, int)':
/usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::Init()'
/usr/bin/ld: /usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::~Init()'
/usr/bin/ld: /tmp/ccrm8b4B.o: in function `main':
/home/whoway/nowcoder/main.cpp:14: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:14: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:16: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:16: undefined reference to `std::ostream::operator<<(int)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:16: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:18: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:18: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:18: undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:19: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:19: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:19: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:19: undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:27: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:27: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:29: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:29: undefined reference to `std::ostream::operator<<(int)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:29: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:31: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:31: undefined reference to `std::cout'
/usr/bin/ld: /home/whoway/nowcoder/main.cpp:31: undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
/usr/bin/ld: /tmp/ccrm8b4B.o: in function `__static_initialization_and_destruction_0(int, int)':
/usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::Init()'
/usr/bin/ld: /usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::~Init()'
/usr/bin/ld: /tmp/ccnsT8ZF.o: in function `__static_initialization_and_destruction_0(int, int)':
/usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::Init()'
/usr/bin/ld: /usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

会报错啊,我们来看一下,比如说gcc 对吧?barber 点c p p 啊,m 点c pp select 点c pp,然后呢杠o 啊。 一个可执行文件,比如说生成一个面啊。好,然后呢杠g 是不是加上一个这个参数啊回撤啊,那么这样呢他会呃包一些错误,他说什么呀?他说。 什么什么卫星e 的引用其实就是他找不到这个c 加加的一些库啊,是吧?好,那么这样呢我们用这个g 佳佳啊去进行一个编译啊,回车。 好,是不是宣传好了?

whoway@ubuntu:~/nowcoder$ g++ bubble.cpp main.cpp select.cpp -o main -g
whoway@ubuntu:~/nowcoder$ ls
bubble.cpp  main  main.cpp  select.cpp  sort.h  test.c

1
2
3
4

生成了一个可以调试的啊可执行文件面。好,那我们通过gdp 呀。去打开这个面啊。好,那么现在呢我输入这个l 或者list 啊,那默认呢注意看了,默认它是。显示什么呢?显示这个main函数,因为我们可执行程序啊,他是不是从main函数开始啊,这个进入的对吧?开始执行啊,所以呢他默认去显示的是。这个慢函数所在的那个文件其实就是这个啊慢点c p p 那个文件里面的代码啊,大家看是不是这样的啊,然后继续按ll 它是不是。 继续往下去显示啊。那么现在如果说我想啊去查看这个八b 点c pt 啊,我们我们在这呢再去打开一个这个。 废话啊。cd 到linux 啊,listen 八。 好,比如说呢我们想去这个barber 点c p p 里面去查看它里面的代码。那这个时候怎么办呢?这个时候呢我们应该这样去使用啊。 或者l 然后呢是文件名啊,文件名指定要看哪个文件里面的这个啊具体的代码啊,后面呢跟上这个行号或者呢跟上函数名啊,跟他行号的话。

(gdb) l selectSort(int*, int) 
1	#include "sort.h"
2	#include <iostream>
3	
4	using namespace std;
5	
6	void selectSort(int *array, int len) {
7	
8	    for (int j = 0; j < len - 1; j++) {
9			for (int i = j + 1; i < len; i++) {
10				if (array[j] > array[i]) {
(gdb) l sort.h:3
No source file named sort.h.
(gdb) l select.cpp:3
1	#include "sort.h"
2	#include <iostream>
3	
4	using namespace std;
5	
6	void selectSort(int *array, int len) {
7	
8	    for (int j = 0; j < len - 1; j++) {
9			for (int i = j + 1; i < len; i++) {
10				if (array[j] > array[i]) {
(gdb) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

是去查看指定的这个行号的代码,对吧?当然是这个上下文那个代码。

(gdb) l select.cpp:selectSort
1	#include "sort.h"
2	#include <iostream>
3	
4	using namespace std;
5	
6	void selectSort(int *array, int len) {
7	
8	    for (int j = 0; j < len - 1; j++) {
9			for (int i = j + 1; i < len; i++) {
10				if (array[j] > array[i]) {

1
2
3
4
5
6
7
8
9
10
11
12

那么接着呢大家再来看,就是说啊我们现在呢是呃每一次调用这个list,它只显示十行代码了,对不对?

那么这个呃显示的行数我能不能去啊,查看或者说修改它了啊,是可以的啊。那么我们如何去设置显示的行数呢?啊,就是这个。 set list. 啊,那注意了这个list 的它其实是一个简写,是list size i 的一个简写啊,list size 是不是就是啊行数啊,对吧?大小对吧? 列出的一个大小啊,然后后面的跟上行数啊,然后呢也可以去显示啊,我默认显示多少。行,那就是税务list 或者。

Reading symbols from main...
(gdb) l
1	#include <iostream>
2	#include "sort.h"
3	
4	using namespace std;
5	
6	int main() {
7	
8	    int array[] = {12, 27, 55, 22, 67};
9	    int len = sizeof(array) / sizeof(int);
10	
(gdb) show listsize 
Number of source lines gdb will list by default is 10.
(gdb) list main.cpp	【啊,那么这样呢他呃错误啊,我们不能直接这样去操作,我们后面呢要带上这个行号,或者呢是它的一个。这个函数的名称啊不能直接写一个文件】
Function "main.cpp" not defined.
(gdb) show list
Number of source lines gdb will list by default is 10.
(gdb) set listsize 20
(gdb) l
11	    bubbleSort(array, len);
12	    
13	    // 遍历
14	    cout << "冒泡排序之后的数组: ";
15	    for(int i = 0; i < len; i++) {
16	        cout << array[i] << " ";
17	    }
18	    cout << endl;
19	    cout << "===================================" << endl;
20	
21	    int array1[] = {25, 47, 36, 80, 11};
22	    len = sizeof(array1) / sizeof(int);
23	    
24	    selectSort(array1, len);
25	    
26	    // 遍历
27	    cout << "选择排序之后的数组: ";
28	    for(int i = 0; i < len; i++) {
29	        cout << array1[i] << " ";
30	    }
(gdb)  show listsize 
Number of source lines gdb will list by default is 20.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 4.断点的设置

(gdb) b 9
Breakpoint 1 at 0x137b: file main.cpp, line 9.
(gdb) info break
Num     Type           Disp Enb⭐️ Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9

⭐️⭐️⭐️Enb (这是英语单词enable的缩写,Y表示yes,N是No)也就是断点生效与否

(gdb) b 11
Breakpoint 2 at 0x1382: file main.cpp, line 11.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9
2⭐️       breakpoint     keep y⭐️   0x0000000000001382 in main() at main.cpp:11
(gdb) disable 2⭐️
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9
2       breakpoint     keep n⭐️   0x0000000000001382 in main() at main.cpp:11

Enb为No之后,将来,你虽然打了断点,但是程序到这,不会停,除非你重新yes
(gdb) enable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9
2       breakpoint     keep y   0x0000000000001382 in main() at main.cpp:11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 条件断点(一般在循环)

  • 然后呢我们还可以这样就是设置一些条件断点啊,那么这个设置条件断点呢一般是用在这个循环的位置。
(gdb) l
11	    bubbleSort(array, len);
12	    
13	    // 遍历
14	    cout << "冒泡排序之后的数组: ";
15	    for(int i = 0; i < len; i++) {
16	        cout << array[i] << " ";	⭐️
17	    }
18	    cout << endl;
19	    cout << "===================================" << endl;
20	
(gdb) b 16
Breakpoint 3 at 0x13b5: file main.cpp, line 16.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9
2       breakpoint     keep y   0x0000000000001382 in main() at main.cpp:11
3       breakpoint     keep y   0x00000000000013b5 in main() at main.cpp:16
(gdb) d 3
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9
2       breakpoint     keep y   0x0000000000001382 in main() at main.cpp:11
(gdb) b 16 if i=3		⭐️
Breakpoint 4 at 0x13b5: file main.cpp, line 16.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000137b in main() at main.cpp:9
2       breakpoint     keep y   0x0000000000001382 in main() at main.cpp:11
4       breakpoint     keep y   0x00000000000013b5 in main() at main.cpp:16
	stop only if i=3		⭐️(有说明)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

​ 啊,好,那举个例子啊,比如说我们啊。现在去查看第一行。啊,再再再去查看一下。大家看一下我账号是不是有一个货循环啊,还有一个破循环,我们可以在这个第十六行啊打个断点,比如说呃break。十六后面呢我们加上去条件条件是什么呢?义务因为什么呢?我们这个i s 不是一个变量啊,对吧?那我们可以让这个i 呀。 在你看这个楞寺庵,小于愣死愣死的设计啊,一二三四五对吧?那我们可以在这个地方呢打一个断点。 让这个i 呀为比如说为三的时候啊,

  • i为 3的时候我这个断点呢才停在这
  • 那当你这个i=0,1,2的时候。虽然你在这打了断点,但是程序听嘛?不停对吧?
  • 因为我们打的是这个条件,断点啊,回车。

好,然后呢,我们id 看一下。 你看一下,这是第六个观点嘛,对不对?他是在第十六行到的。然后呢,他是不是也有一个这个说明,他说。stop n line, if i 等于三是吧?也就是说,当我这个i 等于三的时候,这个断点他才会停在的,是吧?哎,这是我们啊设置的这个条件断点啊。好了,那这个是我们如何去在这个gdp 当中啊去设置断点,对吧? 那设置断点啊,非常简单。

设置好了以后呢,接下来我们是不是就要让我们的程序去运行啊,对吧?运行了以后程序停到这个断点处。 啊,然后我们是不是就可以去查看这个代码当中的一些变量,它的值是不是正确的,对吧?然后呢分析一下咱们这个程序呢哎是不是有问题。

# 16.GDB调试4

现在呢这个断点呢我们已经设置好了啊那。设置好了以后呢,接下来呢我们要让这个g d p 程序啊给大家运行起来,对吧?那现在呢我们并没有去运行我们的啊g d p 程序啊。

  • 我们之前呢输入的这个gdb命令啊,它只是去打开gdb调试工具啊, 并没有去运行我们的g d p 程序。所以呢我们接下来呢。

让我们g d b 这个调试工具啊去操作我们的程序啊,让这个程序呢启动起来。

那如果说你在这个程序当中啊啊设置了这个端点的话呢,那程序呢才会停到我们的啊这个设置的断点上,对吧?所以呢接下来呢给大家去介绍一下。这个g d b 啊调试相关的一些命令。 那我刚才说了,我们要去调试这个程序啊,对吧?首先我们要打断点对吧?那断点呢我们已经设置好了。那接下来呢要让gdp 程序啊给它运行起来。

好,那么运行gdp 程序啊,它有两个命令,一个呢是start,start的是不是就是开始的意思,对吧?那么这个大的呢,它是啊把。我们这个程序啊运行起来以后呢,它会停在第一行啊他会停在第一行。然后还有一个命令呢是这个wrong 啊,那rush 不就是跑起来,对吧?让我们程序跑起来。 啊,那么他呢是呃,程序运行起来以后啊啊只有遇到这个断点的地方呢,它才会停啊。那也就是说这个大的跟这个run 呢。 的区别啊就在于start 呢它是程序运行起来以后呢,它就直接停在第一行了。

  • 啊,那么如果说我们要想从这个程序的啊这个第一行开始。啊,往下呢去调试我们的程序,那我们就可以使用这个start的啊。

  • 那么如果说呢你要呃让这个程序啊运行起来以后呢,哎停在你自己啊。设置的这个第一个断点上。那么我们可以用这个run 啊,这是他们的一个区别。

然后呢,还有一些其他的,比如说呢呃我们可以继续去运行我们的这个程序,对吧?比如说我们现在呢已经停到了一个断点上了啊,我想让这个程序呢继续往下去运行。啊,然后呢到下一个断点来停止,我们可以使用这个啊continue 啊,简写呢就是c 对吧?continue 就是继续的意思。

那或者呢我们还可以向下去执行1行代码啊,用这个next 啊简写呢就是n 那么这个呢它是呃向下执行啊。比如说我们遇到了一个个调用函数对吧?我们调用一个函数,那么它是把整个这个函数呢都执行完的,它是不会进入到函数体里面的

啊,那么这个跟我们后面。啊,要讲的另外一个命令就是step 啊,节选呢是s 那它呢也是向下去执行1行代码,那它呢是单步调试啊。那当他遇到这个函数体的时候呢,他会进入到这个函数体当中啊,就是说进入到函数体当中。然后呢一行一行的往下执行啊。

然后呢还可以设置这个自动变量啊。number 啊,然后呢,显示这个我设置的这个自动变量啊,我们用info 或者i 啊,然后后面跟上display。那之前呢我们显示这个断点是不是。info break 对吧?啊,那这样呢变成了display。那取消这个自动变量呢就是on display。后面呢跟上这个啊自动变量的一个编号啊那。

什么是设置这个自动变量?我们后面呢啊给大家演示的时候呢,我们在详细的去说哈。然后呢还有一些其他的操作。比如说我们可以设置一个变量的值。啊,比如说set far 啊,这是固定的啊,比如说我要设置一个变量的值,后面呢是变量名等于变量值啊,然后呢还有像这个跳出啊这个函数体,我们可以用finish。对吧,毕竟是就是结束的意思。那跳出循环呢,我们用这个until对吧?until条跳出循环啊。好,那这些呢是我们调试程序啊。啊,相关的一些命令啊,那当然了,这个调试程序相关的命令呢还有很多啊,那么我们常用到的呢就是这些啊,而且这些呢是最基础的。

  • ==那我们学完这些以后呢,同学们呢可以自己呢去通过gdp 的一个帮助文档啊,去查看一些其他的这个调试命令的使用啊。==

好,那下面呢就给大家去演示一下这些啊调试命令。

​ 我们先给大家呢也是这个啊多个文件的。啊,这个调试啊,好,那我们怎么去操作啊,是不是gdp 对吧?后面呢跟上可执行文件回车。那么注意了,现在呢我们只是打开了g d b 这个。工具调试工具并没有去运行我们的这个man 这个可执行程序,对吧?那我要怎么去运行呢?

啊,我在这呢可以输入这个。start at. 啊,或者呢输入这个wrong 对吧?那么注意,现在我有没有打断点? 注意了,我如果说我退出了g d p 啊,那它的端点呢就全部没有了啊,那你重新进来以后呢,他呃还需要重新去设置断点。好,那大家看一下。我现在呢i b 现在是不是没有断电,没有任何的概念吗?对吧?我输入这个指令叫sstart啊,那么大家看一下他停在哪儿了,大家看一下,他说temporary break point 一啊,在这个卖函数在慢点c p p 里面第六行。 是不是就是停在这个曼函数啊,对不对?也就是我们程序的第一行嘛,是吧?好,那这是呃这个start它的一个作用啊。

whoway@ubuntu:~/nowcoder$ gdb main
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 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-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 main...
(gdb) start
Temporary breakpoint 1 at 0x133d: file main.cpp, line 6.
Starting program: /home/whoway/nowcoder/main 

Temporary breakpoint 1, main () at main.cpp:6
6	int main() {
(gdb)  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

然后呢,我们比如说呢我们现在呢要呃继续往下执行,我们是不是可以按这个c 啊啊那rc 的话呢它是呃继续往下执行。 直到遇到下一个断点会停止。那现在呢我们是不是没有其他的专家啊,那么他会停在哪啊?他是把这个程序给运行完了回去啊,你看。 程序就运行完了,是不是?好,然后呢再演示一下这个run 啊。那run 的话,我们现在没有打断点,是不是,呃,我们run 的话,他没有断点呢。停在哪?那么整个程序是不是也会运行,我啊回车,你看是不是整个程序也运行完了,你看他把这个呃排序后的一个结果都给我们输出出来吧。

(gdb) start
Temporary breakpoint 1 at 0x133d: file main.cpp, line 6.
Starting program: /home/whoway/nowcoder/main 

Temporary breakpoint 1, main () at main.cpp:6
6	int main() {
(gdb)  c
Continuing.
冒泡排序之后的数组: 12 22 27 55 67 
===================================
选择排序之后的数组: 11 25 36 47 80 
[Inferior 1 (process 837476) exited normally]
(gdb)  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • 如果没有断点,使用run
whoway@ubuntu:~/nowcoder$ gdb main
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 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-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 main...
(gdb) r
Starting program: /home/whoway/nowcoder/main 
冒泡排序之后的数组: 12 22 27 55 67 
===================================
选择排序之后的数组: 11 25 36 47 80 
[Inferior 1 (process 837509) exited normally]
(gdb) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 断点被击中一次⭐️「info break」

(gdb) b 16
Breakpoint 1 at 0x5555555553b5: file main.cpp, line 16.
(gdb) r
Starting program: /home/whoway/nowcoder/main 

Breakpoint 1, main () at main.cpp:16
16	        cout << array[i] << " ";
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00005555555553b5 in main() at main.cpp:16
	breakpoint already hit 1 time⭐️⭐️⭐️

1
2
3
4
5
6
7
8
9
10
11
12

# 跳出循环

  • 我们如果要跳出1个循环,需要满足一些条件:

  • 1、首先循环里面不能有断点/或该断点不可用

  • 2、然后,我们要执行到循环的最后一行

    • 也就是我们循环开始的一行for(int i=0; i<len; ++i)
  • 3、在这行使用until

    (gdb) i b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x00005555555553b5 in main() at main.cpp:16
    	breakpoint already hit 4 times
    (gdb) d 1
    (gdb) l
    11	    bubbleSort(array, len);
    12	    
    13	    // 遍历
    14	    cout << "冒泡排序之后的数组: ";
    15	    for(int i = 0; i < len; i++) {
    16	        cout << array[i] << " ";
    17	    }
    18	    cout << endl;
    19	    cout << "===================================" << endl;
    20	
    (gdb) until
    15	    for(int i = 0; i < len; i++) {	⭐️⭐️⭐️(程序停在第16行)
    (gdb) p i
    $5 = 3
    (gdb) until
    18	    cout << endl;	⭐️直接到第18行了
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

# 跳出函数体finish

Reading symbols from main...
(gdb) l
1	#include <iostream>
2	#include "sort.h"
3	
4	using namespace std;
5	
6	int main() {
7	
8	    int array[] = {12, 27, 55, 22, 67};
9	    int len = sizeof(array) / sizeof(int);
10	
(gdb) l
11	    bubbleSort(array, len);
12	    
13	    // 遍历
14	    cout << "冒泡排序之后的数组: ";
15	    for(int i = 0; i < len; i++) {
16	        cout << array[i] << " ";
17	    }
18	    cout << endl;
19	    cout << "===================================" << endl;
20	
(gdb) b 11
Breakpoint 1 at 0x1382: file main.cpp, line 11.
(gdb) r
Starting program: /home/whoway/nowcoder/main 

Breakpoint 1, main () at main.cpp:11
11	    bubbleSort(array, len);
(gdb) s
bubbleSort (array=0x3, len=32767) at bubble.cpp:6
6	void bubbleSort(int *array, int len) {
(gdb) s
8	    for (int i = 0; i < len - 1; i++) {
(gdb) finish 
Run till exit from #0  bubbleSort (array=0x7fffffffe380, len=5) at bubble.cpp:8
main () at main.cpp:14
14	    cout << "冒泡排序之后的数组: ";
(gdb) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  • 那我们跳出这个函数啊,也需要满足一些条件。就是说你这个呃函数啊呃里面呢或者说往下不能有这个断点。

因为你成绩往下执行啊,不能遇到断点。如果遇到断点的话,他是不是又停到那个站点那个地方了? 所以说你要把下面的这些断掉啊,比如说啊我们举个例子,

比如说你当前呢是在这个barber sort 这个函数的啊,比如说第一行是吧?那你现在呢想要跳出这个函数了。

那如果说下面有端点的话,那你要把它给干部给他先删除掉啊,然后呢再执行这个finish,他才能够跳出啊他才能够跳出。

# 自动变量(很有用)

​ 好,然后呢我们继续往下执行啊,程序运行完了。好,kate 推出啊。好,然后呢还有一个没有给大家介绍啊,就是我们可以去设置这个啊自动变量啊,那么设置自动变量呢我们拿另外一个案例来看啊。

​ 那现在呢比如说我们想print。a 的值。对吧哎是不是输出了printer 这个a 的值啊,对吧?那我在print b 是不是输出了b 的值,一个是十一个,是三十是吧?那我现在呢我要往下去执行啊,比如说我按这个啊next。他是不是执行到这个for 循环啊,是吧?

​ ==那我想每一次向下去执行的时候呢,都要去输出a 和b 的值。==那这个时候呢啊我们是不是啊,每次都要print a print b 那如果说你有很多的变量的话,你都要去查看的话,是不是都要通过这个print 去输出啊,非常麻烦。那我们可以设置一个自动变量。好,那设置自动变量以后呢,每一次往下执行呢,它都会去。自动打印这个你设置的这个自动变量的值啊,display 后面的跟上这个变量的名称。

​ 啊。好,那我们来设计一下,比如说display。好,比如说a 回撤是不是设置好了,然后display。b 回传是吧?好,然后呢注意看我往下执行啊next。好,大家看向下执行,执行到二十一行,他是不是照样能够输出a 和b 的值,对吧?在那。

哎,你看他是不是每一次往下去执行,都会输出a 和b 的值,对吧?这个就是自动变量啊,那我们还可以通过info,然后display。

(gdb) info display 
Auto-display expressions now in effect:
Num Enb Expression
1:   y  a
2:   y  b
1
2
3
4
5

​ 去查看你设置了哪些自动面料,你看是不是设置了两个,那你要删除的话怎么办呢? ​ 那删除的话呢就是==undisplay==,然后后面跟上这个编号就行了啊。比如说我们on this,the play, 比如说一回撤啊啊那他这样呢,他说什么,他说。没有定义的这个呃,命令是吧?我写错了啊。这是play。

(gdb) display a
1: a = 10
(gdb) display b
2: b = 30
(gdb) info display 
Auto-display expressions now in effect:
Num Enb Expression
1:   y  a
2:   y  b
(gdb) undisplay 1
(gdb) n
a + b = 40
20	    for(int i = 0; i < a; ++i) {
2: b = 30
(gdb) info display 
Auto-display expressions now in effect:
Num Enb Expression
2:   y  b
(gdb) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# set修正bug,继续调试

​ 所说的这个设置条件按钮,对吧?好,然后呢我们在这个地方呢还可以设置变量它的一个值。啊,那比如说呢我们现在呢在调试对吧?发现这个。呃,里面呢有一个变量,比如说这个i 的值啊,跟我们预想的不一样。但我想改正一下,对吧?那我们可以通过这个set 头发啊,然后变量名等于一个值,比如说。 ​ 呃,让这个i 呢等于啊你注意看我们现在呢这个货循环,它是循环几次,我们来看一下

(gdb) b 24
Breakpoint 1 at 0x125a: file test.c, line 24.
(gdb) run
Starting program: /home/whoway/nowcoder/test 
argc = 1
a = 10, b = 30
a + b = 40
i = 0

Breakpoint 1, main (argc=1, argv=0x7fffffffe4b8) at test.c:24
24	        printf("res value: %d\n", res);
(gdb) p res
$1 = 0
(gdb) set var res=99
(gdb) p res
$2 = 99

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 啊,就是说有的时候呢我们可以用到这个set var这个命令去设置某一个变量的值啊,让它等于我们想要的这个值,对吧?
  • 那设置好了以后,我们可以继续往下去。啊,调试其他的这个代码,然后呢去找出其他的bug

​ 那么到这呢啊我们这个gdb啊要求大家所掌握的一些内容呢,就已经给大家全部介绍完了啊。至于一些其他的这个命令呢,大家可以自己去查看一些资料啊,自己去学一学啊。

# 0.代码

# main.cpp

#include <iostream>
#include "sort.h"

using namespace std;

int main() {

    int array[] = {12, 27, 55, 22, 67};
    int len = sizeof(array) / sizeof(int);

    bubbleSort(array, len);
    
    // 遍历
    cout << "冒泡排序之后的数组: ";
    for(int i = 0; i < len; i++) {
        cout << array[i] << " ";
    }
    cout << endl;
    cout << "===================================" << endl;

    int array1[] = {25, 47, 36, 80, 11};
    len = sizeof(array1) / sizeof(int);
    
    selectSort(array1, len);
    
    // 遍历
    cout << "选择排序之后的数组: ";
    for(int i = 0; i < len; i++) {
        cout << array1[i] << " ";
    }
    cout << endl;

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# select.cpp

#include "sort.h"
#include <iostream>

using namespace std;

void selectSort(int *array, int len) {

    for (int j = 0; j < len - 1; j++) {
		for (int i = j + 1; i < len; i++) {
			if (array[j] > array[i]) {
				int temp = array[j];
				array[j] = array[i];
				array[i] = temp;
			}
		}
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# sort.h

#ifndef SORT_H_
#define SORT_H_

void bubbleSort(int *array, int len);

void selectSort(int *array, int len);

#endif
1
2
3
4
5
6
7
8

# test.c

#include <stdio.h>
#include <stdlib.h>

int test(int a);

int main(int argc, char* argv[]) {
    int a, b;
    printf("argc = %d\n", argc);

    if(argc < 3) {
        a = 10;
        b = 30;
    } else {
        a = atoi(argv[1]);
        b = atoi(argv[2]);
    }
    printf("a = %d, b = %d\n", a, b);
    printf("a + b = %d\n", a + b);

    for(int i = 0; i < a; ++i) {
        printf("i = %d\n", i);
        // 函数调用
        int res = test(i);
        printf("res value: %d\n", res);
    }

    printf("THE END !!!\n");
    return 0;
}

int test(int a) {
    int num = 0;
    for(int i = 0; i < a; ++i) {
        num += i;
    }
    return num;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# bubble.cpp

#include "sort.h"
#include <iostream>

using namespace std;

void bubbleSort(int *array, int len) {

    for (int i = 0; i < len - 1; i++) {
		for (int j = 0; j < len - 1 - i; j++) {
			if (array[j] > array[j + 1]) {
				int temp = array[j];
				array[j] = array[j + 1];
				array[j + 1] = temp;
			}
		}
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 参考资料