【问题标题】:Disable compile out禁用编译
【发布时间】:2014-05-24 15:47:36
【问题描述】:

有没有办法指示 g++ 或 clang 不要编译出代码中未使用的变量?我知道大多数编译器会编译出不影响最终输出的部分代码。出于调试原因,我想知道是否有办法禁用它?

【问题讨论】:

    标签: c++ c g++ clang compiler-optimization


    【解决方案1】:

    是的。在 gcc(可能还有 clang)中,您可以使用 -O0 进行编译。这将禁用所有优化。您也可以使用-Og,它不应该删除变量。此标志仅启用“调试器友好”优化。

    【讨论】:

    • 你应该结合 -Og 和 -g 来指示编译器保留调试符号。
    • -O 标志和 -g 标志是分开的。当错误只发生在更高的优化级别时,-g 非常有用。
    【解决方案2】:

    只需声明变量volatile。这具有在任何编译器上工作的优势,而无需编译器特定的扩展或命令行选项 - 它还允许您具体了解哪些变量得到了这种处理。如果您希望能够删除发布版本的 volatile,您可以使用以下内容:

    #if defined NDEBUG
        #define DEBUG_VOLATILE
    #else
        #define DEBUG_VOLATILE volatile
    #endif
    

    然后声明如:

    DEBUG_VOLATILE debug_var = 0 ;
    

    仅在调试版本中是可变的。

    【讨论】:

    • 我看不出为什么编译器无法删除未使用的 volatile 变量?
    • @Voo:我认为这是“在实践中”而不是“按语言定义”的情况。
    【解决方案3】:

    也许:

       int foobar __attribute__((used));
    

    文档http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html 说(强调):

    此属性附加到具有[sic] 静态 存储的变量,意味着即使看起来未引用该变量,也必须发出该变量。

    更新 1:也许这是https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem,也就是说,您真正要解决的问题是什么?

    无论如何,正如dma 在评论中指出的那样,这个解决方案会受到影响,因为“添加到代码中的任何东西都将更难于非调试版本中删除”。同意。

    更新 2:用 -s 编译这个 4 行文件:

    int                              foo1 = 111;
    static int                       foo2 = 222;
    static int volatile              foo3 = 333;
    static int __attribute__((used)) foo4 = 444;
    

    给出(删节):

    .globl foo1
        .data
    foo1:
        .long   111
    foo4:
        .long   444
    

    也就是说,变量foo3,使用克利福德对volatile 的建议,被编译出,而foo4 被保留。 (gcc 4.1.2)

    但是,另一方面,编译:

    void bar(void) {
        int                        bar2 = 222;
        int volatile               bar3 = 333;
        int __attribute__ ((used)) bar4 = 444;
    }
    

    给予:

    警告:“使用”属性被忽略

    和:

    movl    $333, -4(%ebp)
    

    所以情况正好相反:volatile 有效,__attribute__ ((used)) 无效(可能是意料之中,因为 bar4 不是 static)。

    【讨论】:

    • 为了调试,最好调整编译器的命令行。对于非调试版本,添加到代码中的任何内容都将更难删除。
    • @dma:在某些情况下,这种方法的选择性可能是一个优势。对于删除,您可以使用与我的答案相同的模式,仅用于属性。需要注意的重要一点是,这仅适用于具有静态存储类的变量(即全局变量和显式静态变量)。
    猜你喜欢
    • 2018-12-27
    • 2017-07-14
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 2019-07-13
    相关资源
    最近更新 更多