基础知识
GDB优化编译
-O0 是gcc编译器的一个优化选项,它表示不进行任何优化。
在编译程序时,编译器可以对程序进行一系列的优化,以提高程序的执行效率和减小程序的空间占用。例如,编译器可以将一些常量表达式进行计算,删除不可达代码,减少函数调用等操作。但是,这些优化操作可能会导致程序的调试变得困难,因为优化后的代码与原始代码可能存在差异,使得调试器难以准确地定位程序中的错误。因此,在调试程序时,通常会使用`-O0`选项来关闭所有的优化操作,以便生成与原始代码最相近的可执行文件,以方便调试。
例如,可以使用以下命令将名为`program.c`的C源文件编译成名为`program`的可执行文件,并关闭所有的优化操作:
gcc -O0 -o program program.c需要注意的是,关闭所有的优化操作可能会导致程序的执行效率降低,因此在生产环境中,通常会使用其他的优化选项来提高程序的执行效率。但是,在调试程序时,为了方便调试,仍然需要使用`-O0`选项来关闭所有的优化操作。
编译教程
一般调试
1. 编译程序时添加-g选项,以便在程序中嵌入调试符号。例如,在使用gcc编译C程序时,可以使用以下命令:
gcc -g -o program program.c2. 启动gdb,并加载程序。例如,可以使用以下命令启动gdb,并加载名为program的程序:
gdb program3. 在gdb中设置断点。使用命令`break`或缩写命令`b`设置断点。例如,在程序的第10行处设置一个断点:
b 10如果要设置在某个函数内的断点,可以使用以下命令:
b function_name如果要设置在某个文件内的断点,可以使用以下命令:
b file_name:line_number4. 运行程序。使用命令`run`或缩写命令`r`运行程序,例如:
r5. 程序运行到断点处时停止。当程序运行到设置的断点处时,gdb会暂停程序的执行,并显示当前代码行。
6. 使用gdb的命令进行调试。在程序暂停执行时,可以使用gdb的命令进行调试,例如:
- 使用`next`或缩写命令`n`执行下一行代码。
n- 使用`step`或缩写命令`s`进入函数或跳过函数调用。
s- 使用`print`或缩写命令`p`打印变量的值。
p variable_name- 使用`backtrace`或缩写命令`bt`查看函数调用栈。
bt- 使用`continue`或缩写命令`c`继续执行程序。
c- 使用`watch`设置变量监视点,当变量的值发生变化时,程序会停止执行。
watch variable_name- 使用`info`命令查看程序的信息,例如查看当前断点列表、查看内存信息等。
info breakpoints
info memory7. 在程序执行过程中可以随时添加或删除断点,使用`delete`命令删除断点,例如:
-使用`delete`命令删除所有断点。
delete- 使用`delete breakpoint`删除指定的断点。
delete breakpoint breakpoint_number8. 在调试完成后,使用`quit`命令退出gdb。
quit需要注意的是,在使用gdb进行调试时,需要熟悉gdb的常用命令,并根据实际情况进行调试。
崩溃或段错误
如果程序崩溃或出现段错误,可以使用`coredump`命令查看程序的core文件,以了解程序崩溃的原因。具体使用方法如下:
1. 在编译程序时添加-g选项,并使用`-fno-omit-frame-pointer`选项禁用帧指针优化。
gcc -g -fno-omit-frame-pointer -o program program.c2. 运行程序,如果程序崩溃,会生成一个名为core的core文件。
3. 使用gdb加载程序和core文件,以查看程序崩溃的原因。
gdb program core
4. 使用`bt`命令查看函数调用栈,以找出程序崩溃的原因。
bt
总之,使用gdb进行程序调试可以帮助我们快速定位代码中的错误,并提高代码调试的效率。需要注意的是,在使用gdb进行调试时,需要根据具体情况进行调试,并注意代码中的潜在问题,避免在进行调试时出现一些不必要的错误。
实例
准备
文件夹里有两个 .c 文件
编译
gcc -c array.c main.c
添加 -g
gcc -O0 -g -o program array.o main.o
执行发现65被输出了17次,而按设想是输出16次(后面发现数错了,bug不在这里)。
使用gdb调试,进入这个页面表示成功
gdb program
猜测是输出子程序的问题,我直接添加断点
b array_print
运行开始调试,在断点处停下了
r
从这里开始,我发现有问题,第一是我原来gdb的这个文件,没有编译标志,本来直接把两个c文件gcc -g即可,我先编译到两个o文件了,可能是这个原因导致的,
所以我重新编译了一下。
先list一下,展现一下文件,开始调试
添加一个断点,这个断点本来想添加在array_add的,看眼瞟了。
b 11
开始运行.
r
不进入函数跳过
n
找到个问题,i = 16 的时候还执行了一次循环,i = 17 时才跳出,此时 array_add被执 行了17次,此时array_a array_b也有值,说明前面也有 问题。
重新调试一次,找到三个数组第17个数字的值,有错误
结果虽然没因为bug出现问题,但多赋值要修改,节省内存。
使用nano编辑器修改
nano array.c
bug修复!