gcc/g++是GUN编译器下的一个编译器组件。本文主要记录学习使用gcc/g++命令相关的参数,以及使用gdb工具对c++的调试。
gcc特点:
- 其是一个可以移植的编译器,支持多种硬件平台
- 不仅是个本地编译器,还可以跨平台交叉编译。如嵌入式程序可在x86上编译,然后在arm上运行。
- 有多种语言前端,用于解析不同语言
- 是自由软件,任何人都可以使用或更改这个软件
gcc和g++区别:
- 不管是gcc还是g++都可以编译C程序,编译程序的规则和参数都相同
- g++可以直接编译C++程序,gcc编译C++程序需要额外添加参数
-lstdc++
- 不管是gcc还是g++都可以定义
__cplusplus
宏
本文命令以g++
为例示范
gcc工作流程
gcc编译器对程序的编译主要分为四个步骤。如下所示:
- 预处理:在这个阶段主要进行三件事:展开头文件、宏替换、去掉注释行(构建后得到的目标文件不包含注释内容,源文件中添加多少注释对最后的文件的大小没有影响。)
此阶段需要gcc调用预处理器完成,最终得到是一个以.i
后缀结尾的文件。
例子:g++ -E t.cpp -o t.i
注意:如果直接执行g++ -E t.cpp
预处理的结果会显示到命令行屏幕上。 - 编译和优化:这个阶段需要GCC调用编译器对文件编译,最终将文件转换成汇编语言。文件通常以
.s
结尾。例子:g++ -S t.i -o t.s
,或可直接由cpp
文件得到,g++ -S t.cpp
- 汇编:该阶段调用汇编器对汇编文件进行汇编,得到一个
.o
结尾的二进制文件。g++ -c t.s -o t.o
- 链接:链接器将各种
.o
文件合并,并对文件需要调用的库进行链接,最终得到一个可执行的二进制文件.out
文件(windows上是.exe
文件),可以直接使用g++ t.cpp
进行完成,若是有多个文件可以分开g++ t1.cpp t2.cpp
如此,也可以使用通配符进行完成g++ *.cpp
。该文件在汇编的基础上,增加了函数的具体信息和一些外部变量等等,最终可执行文件可被加载到内存中由操作系统执行。
gcc命令
常用选项:
- -o 产生目标(.i、.s、.o、可执行文件等)
- -E 只运行C预编译器
- -S 告诉编译器产生汇编程序文件后停止编译,产生的汇编语言文件拓展名为.s
- -c 通知gcc取消连接步骤,即编译源码,并在最后生成目标文件
- -D 在程序编译时指定一个宏(类似在程序中定义的宏)
- -Wall 使gcc对源文件的代码有问题的地方发出警告
- -Idir 将dir目录加入搜索头文件的目录路径
- -Ldir 将dir目录加入搜索库的目录路径
- -llib 连接lib库
- -g 在目标文件中嵌入调试信息,以便gdb之类的调试程序调试
g++命令
常用选项:
- -B<directory> 将<director>添加到编译器的搜索路径
- -v 显示编译器调用的程序
- -### 类似于-v,但选项被引用,命令未被执行
- -E 仅预处理;不要编译、汇编或链接
- -S 仅编译;不要组装或连接
- -c 编译和汇编,但不链接
- -o<file> 将输出放入<file>。
- -shared 创建共享库
- -x 指定以下输入文件的语言。允许的语言包括:c++汇编程序无“none”表示恢复到默认行为,根据文件的扩展名猜测语言。
gdb调试
常用命令(以下都为程序简写)
gdb -p 进程id
调试程序中正在运行的以id为进程编号的程序gdb 程序名
调试某程序l [行号]
默认生成10行,查看正在调试的源码内容,显示的当前调试行的上下5行,可以不指定行号,指定后显示程序以行号为中心的10行代码r
开始调试,直到程序结束或遇到断点暂停。在调试过程中,再次使用r命令会重新开始调试。where
查看此时执行位置b 行号
以l命令显示的内容为基础,在指定行打断点info b
显示全部断点信息,也可以在b后加编号显示指定断点d 断点编号
删除指定断点,不加编号则删除全部c
从当前调试位置直接执行到下一个断点处disable 断点编号
关闭断点 ,关闭断点并不是删除断点。只是在调试时不会在该处暂停,但是断点依旧存在。enable 断点编号
打开断点p 变量
打印i对应的变量值,如p i
,打印i变量的地址值,如p &i
。也可以反过来使用变量的地址和变量的类型来打印出变量的值,这种同样适用于结构体等其它类型p *(int *) 0x7fffffffdf54
、p *(int *) 0x7fffffffdf58
display 变量
常显示指定变量值,使用方式与p一致undisplay 常显示变量编号
删除指定常显示变量s
逐语句调试,相当于vs中的F11n
逐过程调试,相当于vs中的F10continue
从当前位置开始运行,直到遇到下一个断点或者程序运行结束。until 行号
执行至指定行finish
可以直接跑完当前函数,若函数只有一层则直接跑完函数。
如果是函数递归调用,当还没开始递归时,finish会执行完整个函数,自动走完全部递归过程(前提无断点),如我们此时还在main函数中还没执行其中的func(n)函数,会直接执行完所有的递归func函数。如果已经开始进入func中,会执行完当前func返回上一层中。当已经递归调用后,在哪一层递归finish就会返回至它的前一层。disassemble
查看指令附近区域的反汇编,只能在运行过程中使用。shell 指令
在gdb界面中执行linux指令quit
退出
首先要使用g++ -g t.cpp
生成带有调试信息的可执行文件
/*
* @Author: Xu
* @Date: 2023-03-13 10:22:03
* @Last Modified by: Xu
* @Last Modified time: 2023-03-13 10:22:03
*/
#include <iostream>
#include <cmath>
#include <thread>
using namespace std;
int main()
{
std::cout << __cplusplus << std::endl;
cout << 1 << endl;
return 0;
}
接下来在生成的文件的命令行下输入gdb 文件名
,本例为gdb t
注意:若是没有加-g
参数,会出现No symbol “xxx” in current context,同时,gdp会自动记录最近的命令,如果没有输入其他命令,可以按enter键继续执行最近命令。
➜ gdb t
GNU gdb (GDB) 8.2.1
Copyright (C) 2018 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 t...done.