g++ 与 gdb 常用操作
一、什么是g++,gdb ?
g++:GNU的C++编译器。
gdb:GNU发布的类unix系统下的程序调试工具。
gcc与g++的区别:gcc无法链接c++程序。
二、C/C++代码到可执行程序的过程
- 预处理:进行头文件展开、宏替换、去掉注释和条件编译等(生成 *.i 文件)。
- 编译:检查代码无语法错误后,生成汇编语言代码(生成 *.s 文件)。
- 汇编:将汇编语言代码生成机器码(生成目标文件 *.o)。
- 链接:链接目标文件生成可执行文件(*.out)。
g++常用参数及其作用
参数 | 作用 |
---|---|
-E | Preprocess only; do not compile, assemble or link. |
-S | Compile only; do not assemble or link. |
-c | Compile and assemble, but do not link. |
-o < file > | Place the output into < file >. |
-g | 为调试程序(如gdb)生成相关信息. |
即:
- -E:仅进行预处理,不进行编译、汇编与链接;
- -S:仅编译,不进行汇编与链接;
- -c:编译并汇编,但不进行链接;
- -o:指定输出文件。
三、一个简单的 “Hello World!”。
#include<iostream>
#define Hello "Hello World!"
int main()
{
std::cout << Hello << std::endl;//此处利用宏输出“Hello World!”
return 0;
}
执行g++ file.cpp -E -o file.i,得到结果:
# 1 "file.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "file.cpp"
# 1 "/usr/include/c++/8/iostream" 1 3
# 36 "/usr/include/c++/8/iostream" 3
# 37 "/usr/include/c++/8/iostream" 3
# 1 "/usr/include/c++/8/x86_64-redhat-linux/bits/c++config.h" 1 3
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 4 "/usr/include/c++/8/x86_64-redhat-linux/bits/c++config.h" 2 3
# 2180 "/usr/include/c++/8/x86_64-redhat-linux/bits/c++config.h" 3
# 2180 "/usr/include/c++/8/x86_64-redhat-linux/bits/c++config.h" 3
namespace std
{
typedef long unsigned int size_t;
typedef long int ptrdiff_t;
typedef decltype(nullptr) nullptr_t;
}
...
...
# 2 "file.cpp" 2
# 3 "file.cpp"
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
可以看到宏与注释被替换和处理掉了。
执行g++ file.i -S -o file.s,得到结果:
file "file.cpp"
.text
.section .rodata
.type _ZStL19piecewise_construct, @object
.size _ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
.zero 1
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.LC0:
.string "Hello World!"
.text
.globl main
.type main, @function
main:
.LFB1518:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %esi
movl $_ZSt4cout, %edi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
movq %rax, %rdi
call _ZNSolsEPFRSoS_E
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
...
...
可以看到处理后得到的汇编代码。
继续执行g++ file.s -c -o file.o,得到:
[pig@localhost learn]$ head file.o
ELF>�@@UH������H����]�UH��H���}��u��}�u'�}���u���������UH�����������]�Hello World!GCC: (GNU) 8.2.1 20180905 (Red Hat 8.2.1-3)zRx
�'AbC
y<>A�C
P\A�C
��
%4'>de
s'x���+Cfile.cpp_ZStL19piecewise_construct_ZStL8__ioinit_Z41__static_initialization_and_destruction_0ii_GLOBAL__sub_I_main_ZSt4cout_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6__ZNSolsEPFRSoS_E_ZNSt8ios_base4InitC1Ev__dso_handle_ZNSt8ios_base4InitD1Ev__cxa_atexit
��������
��������E
J��������O
T
Y
继续执行g++ file.o -o file.out,得到可执行文件。执行./file.out,得到:
[pig@localhost learn]$ g++ file.o -o file.out
[pig@localhost learn]$ ./file.out
Hello World!
[pig@localhost learn]$
四、gdb常用命令及作用
在使用gdb调试程序时,需要在g++的参数中加入 -g,然后运行gdb *.out。否则,调试时看到的将是一堆汇编代码。
命令 | 缩写 | 描述 |
---|---|---|
help | h | 获取帮助信息 |
list | l | 显示源代码 |
search | 朝向文件尾部搜索源代码 | |
reverse-search | 朝文件头部搜索源代码 | |
break | b | 设置断点 |
info break | 查看断点信息 | |
clear | 清楚当前行的断点 | |
run | r | 从头运行程序到第一个断点 |
next | n | 单步执行(不进入函数体) |
step | s | 单步执行(进入函数体) |
continue | c | 从当前行继续运行程序至下一断点 |
p | 打印变量值 | |
watch | 设置观察点 | |
set var variable=value | 设置变量variable的值为value | |
bt | 查看运行时栈 | |
quit | q | 退出gdb |
断点相关命令:
命令 | 作用 |
---|---|
b num | 根据行号设置断点 |
b file.c:num | 设置指定文件中的行号断点 |
b function | 根据函数名设置断点 |
b file.cpp:num if(express) | 根据表达时条件在某行设置断点 |
rbreak function* | 对所有function调用设置断点 |
rbreak . | 对所有函数设置断点 |
rbreak file.cpp:. | 对文件中的所有函数设置断点 |
rbreak file.cpp:^express | 对file.cpp中所有express开头的函数设置断点 |
tbreak | 断点仅生效一次 |
ignore num time | 忽略断点号为num的断点time次 |
disable | 禁用所有断点 |
disbale num | 禁用编号为num的断点 |
enable | 启用所有断点 |
enable num | 启用编号为num的断点 |
enable delete num | 启用并在此之后删除编号为num的断点 |
clear | 删除当前行所有断点 |
clear function | 删除函数名为function的断点 |
delete | 删除所有断点、观察点和捕捉点 |
delete num | 删除编号为num的断点 |
End…