【问题标题】:Viewing GCC Optimization Intermediates in GDB?在 GDB 中查看 GCC 优化中间体?
【发布时间】:2015-01-16 04:33:39
【问题描述】:

我有一个 C++ 程序,我正在尝试使用 GDB 进行调试。我正在通过优化构建它,我经常遇到我想调试类似的情况:

int newVar = someArray[thing1 + thing2];

但是,GCC 很聪明,并且会大量优化代码。也许那时只存储中间的thing1 + thing2,而单独的thing1thing2 已被覆盖。当我让 GDB 打印 thing1 时,我得到了 <value optimized out>thing2 也一样。

所以我有两个问题:

  1. 如果我向 gdb 询问p thing1 + thing2,它是否足够聪明地意识到该中间体当前存储在寄存器中?或者它只是试图天真地评估表达式,意识到它使用的两个变量都被优化了,然后失败了?

  2. 如何获得在执行的任何给定点实际可用的表达式评估中间体的列表?如果它将&someArray + sizeof(int) * thing2 存储为中间,我想知道这一点。 GCC 是否没有包含有关其对 GDB 的优化的足够详细信息,以弄清楚实际存储了哪些中间体/编译器如何决定使用每个寄存器?是否有一些我可以指示 GCC 生成的超级详细的多兆字节调试信息格式?是否有其他编译器/调试器对可以更好地处理这个问题?

如果我要花 20 分钟来跟踪函数的程序集,注意 thing1thing2 的来源以及从它们派生的任何内容何时与 someArray 的地址相遇,我将能够手动解决这个问题。但我希望调试器为我做这件事,因为编译器必须首先跟踪所有这些东西才能进行优化。

【问题讨论】:

    标签: c++ debugging gcc optimization gdb


    【解决方案1】:

    如果我让 gdb p thing1 + thing2,它是否足够聪明地意识到该中间体当前存储在寄存器中?

    不,它会尝试幼稚的事情并失败。

    如何获得在执行中的任何给定点实际可用的表达式评估中间体的列表?

    你不能。

    但我希望调试器为我做这件事,因为编译器必须首先跟踪所有这些东西才能进行优化。

    编译器确实跟踪了所有这些东西,但在生成程序集后丢弃了这些信息。没有这些信息,调试器就不可能重建它。 (嗯,理论上是可以做到的,但在实践中,任何充分优化的代码都很难做到。)

    让编译器不丢弃信息在理论上是可能的,但不实用:生成的二进制文件太大了,我不相信当前的调试格式支持“这个复杂表达式的值存储在那个寄存器”的描述很好(如果有的话)。

    【讨论】:

    • GCC/GDB 不支持。显然 MSVC++ 2014 正在获得这样的扩展调试信息,但无论如何它已经有了更清晰的调试格式(单独的 PDB 文件)
    • @MSalters 单独的 PDB 文件与更清晰的格式无关(GCC/GDB 确实支持以类似的方式将调试信息与主要可执行文件分开)。我们无法判断 Microsoft 调试格式是否更清晰:它没有记录在案。我 8 年前使用它的经验告诉我,它绝非如此。
    • 所以我想我的解决方案是“开发并获得合并到 GDB 和 GCC 中的支持,以获得可以做我想做的超详细、超大调试信息格式”。很高兴知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多