C++ 我有一个没有调试信息的二进制版本,用gcc构建,有源代码

C++ 我有一个没有调试信息的二进制版本,用gcc构建,有源代码,c++,debugging,gdb,C++,Debugging,Gdb,当我尝试使用调试模式构建源代码时,所显示的堆栈完全不同,在发布的情况下,在使用gdb的回溯中只显示了一些方法, 为什么会发生这种情况?这是因为在调试模式下有额外的方法,如何在调试和发布模式下使两个方法具有相同的地址。 同样,在这种情况下,我如何构建以获得具有完整堆栈跟踪的准确地址信息。由于我不熟悉在Linux、Windows和pdb文件上进行调试,因此任何帮助都将不胜感激。g++/gcc有许多用于调试程序的选项,但最常见的选项是-g。参考讨论的第一个选项是-g 一些补充资料 例如: 编译不带-g

当我尝试使用调试模式构建源代码时,所显示的堆栈完全不同,在发布的情况下,在使用gdb的回溯中只显示了一些方法, 为什么会发生这种情况?这是因为在调试模式下有额外的方法,如何在调试和发布模式下使两个方法具有相同的地址。
同样,在这种情况下,我如何构建以获得具有完整堆栈跟踪的准确地址信息。由于我不熟悉在Linux、Windows和pdb文件上进行调试,因此任何帮助都将不胜感激。

g++/gcc有许多用于调试程序的选项,但最常见的选项是
-g
。参考讨论的第一个选项是
-g

一些补充资料

例如:

编译不带
-g
的代码:

g++breaked.cpp-o breaked_发布

使用
-g
编译代码:

g++-g breaked.cpp-o breaked\u debug


现在启动
ls-l
并注意文件
breaked\u release
breaked\u debug
之间的大小不同。
breaked\u debug
的大小应大于
breaked\u release
的大小。这是因为它包含调试信息,这些信息可以被调试器使用,如@rockoder答案的注释中所讨论的
gdb

,除了在优化构建中缺少调试符号(将包含在
-g
中)之外,由于内联,整个函数调用可能不再存在

当我尝试使用调试模式构建源代码时,显示的堆栈是 完全不同,在释放的情况下,只有几种方法 显示在gdb的回溯中,为什么会发生这种情况?这是吗 因为在调试模式下有额外的方法

这可能只是由于编译器的优化。您所谓的发布版本可能是在启用编译器速度优化和禁用调试符号的情况下构建的。速度优化包括代码内联,它只是将函数代码复制到位,而不是调用它,所以函数在调用堆栈中不可见。 如果代码是通过一些适当的预处理器检查编写的,那么也可能有一些额外的/不同的方法

在调试和发布中,如何使两个方法具有相同的地址 模式

取决于调试和发布模式。如果它们使用相同的编译器优化,并且只在调试信息上有所不同,那么方法将具有相同的地址。若调试构建并没有优化(-O0在GCC上),那个么方法会更大,因为会做很多不必要的工作,例如在每次操作之前从内存中读取变量,然后再写回。由于每个方法可能更小,函数将具有不同的地址,因为它们通常是一个接一个地打包的

同样在这种情况下,我怎样才能建立一个准确的地址 具有完整堆栈跟踪的信息

启用调试信息。在GCC上,它将是-g3(或-g或类似)。这为代码地址源行查询(来自调试器或崩溃堆栈转储)添加了足够的信息

如果有任何帮助,我将不胜感激,因为我是Linux调试新手, Windows使用pdb文件似乎要容易得多


Windows二进制文件调试有什么显著区别吗?

+1@Manu343726,有。这与这一部分完全相关:“当我试图用调试模式构建源代码时,所显示的堆栈完全不同,在发布的情况下,gdb的回溯中只显示了一些方法,为什么会发生这种情况?”@rerx编写
g++-g
文档并不是对这个问题的回答。。。。答案是缺少调试SIMBOL和编译器在发布模式下执行的优化(如果函数较少,则为内联)。@Manu,像内联这样的真正优化也将发挥作用。但是省略
-g
只是:不提供调试符号。