Linux 命令行入门学习资料 day_4

Linux 命令行入门学习资料 day_4
GCC 调试信息选项-g完全学习手册一、什么是调试信息为什么需要它当我们用 GDB 调试一个程序时我们希望看到源代码的行号变量名和它们的值函数的调用关系但是编译器默认生成的可执行文件是纯机器码里面没有这些人类可读的信息。如果不加特殊选项用 GDB 调试时你只能看到汇编指令和内存地址调试难度极大。调试信息就是由编译器嵌入到可执行文件中的“额外数据”它记录了每一条机器指令对应哪一行源代码每个变量的名字、类型、在内存中的位置每个函数的名称、参数、作用域这些信息让调试器能够把机器码和你的源代码关联起来。二、gcc -g的基本用法作用在编译时生成调试信息以便 GDB 等调试器使用。命令格式gcc-g源文件.c-o输出文件例子gcc-ghello.c-ohello这样编译出的hello程序就包含调试信息可以用 GDB 调试了gdb ./hello如果不加-g会怎样你仍然可以启动 GDB但当你试图列出源代码或打印变量时GDB 会告诉你“No symbol table”或“No line number information”。调试效率极低。三、man gcc中关于-g的官方说明解读版在终端输入man gcc搜索-g你会看到类似下面的描述简化并翻译-gProduce debugging information in the operating system’s native format.GDB can work with this debugging information.On most systems that use stabs format,-genables use of extra debugging information that only GDB can use.Unlike most other C compilers, GCC allows you to use-gwith-O.The shortcuts taken by optimized code may occasionally produce surprising results:some variables you declared may not exist at all;flow of control may briefly move where you did not expect it;some statements may not be executed because they compute constant results or their values are already at hand;some statements may execute in different places because they have been moved out of loops.Nevertheless it proves possible to debug optimized output.关键解读-g生成操作系统原生格式的调试信息GDB 能理解。可以和优化选项-O一起使用这是 GCC 的特色很多编译器优化后不能调试。优化代码的调试可能会产生“奇怪”的现象某些变量可能被优化掉程序执行顺序可能被打乱某些语句可能根本不会执行——但这仍然是可调试的。四、调试信息的级别-g0,-g1,-g2,-g3你可以控制调试信息的详细程度。数字越大信息越详细但可执行文件也越大。选项级别含义-g00不生成任何调试信息与不加-g相同-g11生成最少的信息包括函数名、全局变量但不包含局部变量和行号。适合只需要函数级调用栈的调试。-g或-g22默认级别。包含行号、局部变量、函数参数、结构体定义等。这是最常用的调试信息级别。-g33包含-g2的所有信息再加上宏定义信息。可以在 GDB 里展开宏。一般使用建议日常学习/开发调试用-g等价于-g2就足够了。需要调试宏展开用-g3。发布程序时不要加-g以减少文件体积并保护源代码隐私。五、-g与优化选项-O的关系优化-O1,-O2,-O3会重新组织代码提升运行速度或减小体积。但是这会扰乱源代码和机器码的对应关系。同时使用-g和-O的效果可以调试优化后的代码这是 GCC 的一大优势。但调试体验会下降出现“变量被优化掉”、“单步执行跳来跳去”等现象。初学者黄金法则调试时不加任何-O优化选项只加-g。正确编译调试版本gcc-g-O0hello.c-ohello-O0表示不优化这也是默认值通常可省略。发布时gcc-O2program.c-oprogram不加-g并开启优化。六、其他调试信息格式拓展了解即可-g生成的是系统原生格式你可以指定具体的调试信息格式常用有-ggdb生成专为 GDB 优化的调试信息比默认的-g包含更多 GDB 特有的扩展。-gdwarf生成 DWARF 格式的调试信息现代 Linux 默认使用 DWARF。-gstabs生成 STABS 格式旧格式很少用。通常直接使用-g或-ggdb即可满足所有需求。七、如何检查编译出的文件是否包含调试信息使用file命令filehello输出中如果看到debug_info或not stripped说明包含调试信息。另一个更直观的工具是readelfreadelf-Shello|grepdebug如果有输出列出.debug_*节区说明有调试信息。如果程序是“strip”过的移除了调试信息file会显示stripped。八、实践演示调试信息对 GDB 的影响准备工作创建一个简单的test.c#includestdio.hintadd(inta,intb){intsumab;returnsum;}intmain(){intx10,y20;intzadd(x,y);printf(%d\n,z);return0;}1. 不加-g编译gcc test.c-otest_no_g gdb ./test_no_g在 GDB 里尝试(gdb) list No symbol table is loaded. Use the file command. (gdb) break main Function main not defined.基本无法调试。2. 加了-g编译gcc-gtest.c-otest_with_g gdb ./test_with_g此时(gdb) list 1 #include stdio.h 2 int add(int a, int b) { 3 int sum a b; 4 return sum; 5 } 6 int main() { 7 int x 10, y 20; 8 int z add(x, y); 9 printf(%d\n, z); 10 return 0; (gdb) break main Breakpoint 1 at 0x1149: file test.c, line 7. (gdb) run Breakpoint 1, main () at test.c:7 7 int x 10, y 20; (gdb) print x $1 0 // 还没初始化所以是随机值 (gdb) next 8 int z add(x, y); (gdb) print x $2 10完全可调试源代码、行号、变量一应俱全。九、✅gcc -g速查卡选项作用使用场景-g生成默认级别level 2调试信息日常调试与 GDB 配合-g0不生成调试信息相当于没加-g-g1最少调试信息函数、全局变量只需函数调用栈-g2默认包含局部变量、行号等标准调试需求-g3包含宏定义信息需要调试宏展开时-ggdb针对 GDB 优化的调试信息推荐给 GDB 用户-g -O0调试用关闭优化确保调试时代码行为与源码一致十、动手练习使用man gcc查看-g的完整文档找出其中关于-g和-O同时使用的描述。写一个简单的 C 程序例如计算阶乘分别用-g、-g1、-g3编译然后用readelf -S 文件名 | grep debug观察不同级别生成的调试节区数量有何区别。用-g -O2编译同一个程序进入 GDB尝试单步执行观察是否有“变量找不到”或“执行顺序异常”的现象记录你的发现。用strip 文件名命令移除调试信息再用file命令查看变化体会strip的作用。十一、学习检查清单调试信息究竟包含什么不加-g的后果是什么-g和-ggdb有什么不同如果要在调试时保证源码和机器码严格对应应该配合哪个优化选项如何判断一个可执行文件里有没有调试信息为什么调试优化过的代码可能会让人困惑如果这些问题你都能清晰回答那么gcc -g以及调试信息的核心知识你已经完全掌握了。这份内容可以加入你的命令清单以后每次编译调试程序时-g将成为你的本能选择。