调试选项-g如何更改二进制可执行文件?

问题描述:

编写C/C++代码时,为了调试二进制可执行文件,必须在编译器/链接器上启用调试选项。在GCC的情况下,选项是-g。当启用调试选项时,如何影响二进制可执行文件?允许调试器功能的文件中存储了哪些附加数据?调试选项-g如何更改二进制可执行文件?

-g告诉编译器将符号表信息存储在可执行文件中。除其他事项外,这包括:

  • 符号名
  • 的符号
  • 文件和行号类型的信息,其中的符号从
  • 来到

调试器使用这些信息来为符号输出有意义的名字并将指示与来源中的特定线路相关联。

对于某些编译器,提供-g将禁用某些优化。例如,除非明确指示-O [123],否则icc会使用-g将缺省优化级别设置为-O0。此外,即使您提供了-O [123],仍会禁用阻止堆栈跟踪的优化(例如,从堆栈帧中剥离帧指针,这只会对性能产生较小的影响)。

对于某些编译器,-g将禁用可能会混淆符号来自哪里(指令重新排序,循环展开,内联等)的优化。如果你想用优化进行调试,你可以使用-g3和gcc来解决一些问题。额外的调试信息将包含宏,扩展和可能已被内联的函数。这可以允许调试器和性能工具将优化的代码映射到原始源代码,但这是最好的。一些优化确实破坏了代码。

欲了解更多信息,看看DWARF,调试格式最初设计ELF一起去(在Linux和其它操作系统的二进制格式)。

+1

只是为了增加这一点,它也会减慢可执行文件的速度。我正在用Sun Studio编译器测试一些OpenMP代码,并且通过调试信息,代码运行得更慢。 只是要记住。 – Mike 2008-09-18 03:00:28

一个符号表被添加到可执行程序,它将函数/变量名映射到数据位置,以便调试器可以报告有意义的信息,而不仅仅是指针。这不会影响程序的速度,您可以使用“strip”命令删除符号表。

这与question有一些重叠,它涵盖了另一方面的问题。

正如您感兴趣的问题一样,您可以打开一个hexeditor并查看使用-g生成的可执行文件,以及一个没有生成的可执行文件。您可以看到添加的符号和事物。它也可能改变组件(-S),但我不确定。

-g在可执行文件中添加调试信息,例如变量名称,函数名称和行号。这允许调试器(如gdb)逐行执行代码,设置断点并检查变量的值。由于使用-g的附加信息增加了可执行文件的大小。

另外,gcc允许将-g和-O标志一起使用,这会打开优化。调试优化的可执行文件可能非常棘手,因为变量可能会被优化掉,或者指令可能以不同的顺序执行。通常,使用-g时关闭优化是一个好主意,尽管它会导致代码慢得多。

除了调试和符号信息
谷歌矮(ELF上开发商的笑话)

默认情况下,大多数编译器优化启用调试时关闭。
所以,这段代码是源代码到机器代码的纯粹转换,而不是许多应用于释放二进制文件的高度专业化转换的结果。

但最重要的区别(在我看来)
内存在调试版本通常被初始化为一些编译器特定的值,以方便调试。在发布版本中,除非应用程序代码明确这样做,否则内存不会被初始化。

检查你的编译器文档的详细资料:
但DevStudio的一个例子是:

  • 0xCDCDCDCD分配堆,但不初始化
  • 0xDDDDDDDD释放堆内存。
  • 0xFDFDFDFD“NoMansLand”栅栏自动放置在堆内存边界。不应该被覆盖。如果你重写了一个,你可能会走到数组的末尾。
  • 0xCCCCCCCC分配在堆,但不初始化

一些操作系统(例如z/OS)产生含有调试符号a“侧文件”。这有助于避免使用额外信息膨胀可执行文件。