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

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

-g告诉编译器将符号表信息存储在可执行文件中。 其中包括:

  • 符号名称
  • 键入信息的符号
  • 文件和符号来自的行号

debugging器使用这些信息为符号输出有意义的名称,并将指令与源代码中的特定行相关联。

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

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

有关更多信息,请参阅DWARF ,它是最初devise用于与ELF(Linux和其他操作系统的二进制格式)一起使用的debugging格式。

除了debugging和符号信息
Google DWARF(ELF开发者笑话)

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

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

检查您的编译器文档以获取更多信息
但DevStudio的一个例子是:

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

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

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

此外,gcc允许使用-g和-O标志,这会打开优化。 debugging优化的可执行文件可能非常棘手,因为可能会优化variables,或者可能会以不同的顺序执行指令。 通常,在使用-g时closures优化是一个好主意,尽pipe这会导致代码慢得多。

这个问题与另一方面的问题有一些重叠。

出于利益的考虑,你可以破解一个hexeditor,看一下用-g和一个没有的可执行文件。 你可以看到符号和添加的东西。 它也可能会改变程序集( -S ),但我不确定。

某些操作系统(如z / OS )会生成一个包含debugging符号的“副文件”。 这有助于避免使用额外的信息来扩展可执行文件。