【问题标题】:How can I completely disable calls to assert()?如何完全禁用对 assert() 的调用?
【发布时间】:2011-07-18 06:43:29
【问题描述】:

我的代码中充满了对assert(condition) 的调用。 在调试版本中,我使用g++ -g 来触发我的断言。 出乎意料的是,在我的发布版本中也触发了相同的断言,即编译时没有-g选项。

如何在编译时完全禁用我的断言?我是否应该在我生成的任何构建中明确定义NDEBUG,无论它们是调试、发布还是其他任何东西?

【问题讨论】:

  • 有点离题:如果你想要调试信息,-g 相当于-g2-g3 可能是更好的选择,因为它提供了最具象征意义的信息。例如,在-g3,符号#defines 将可用。不过,我似乎有些工具链在-g3 上卡住了。此外,许多外部库还依赖 -DDEBUG 进行“调试”构建(Posix 仅证明 -DNDEBUG 用于“发布”构建)。

标签: c++ c assert


【解决方案1】:

您必须#define NDEBUG(或将标志-DNDEBUGg++一起使用)这将禁用断言,只要它是在包含断言头文件之前定义的。

【讨论】:

  • 必须在#include <assert.h>之前?
  • @LeiYang 好像必须加在最后#include <assert.h>之前。
【解决方案2】:

使用#define NDEBUG

7.2 诊断

1 标头定义assert宏,并引用另一个宏,

NDEBUG

这不是由<assert.h> 定义的。 如果 NDEBUG 被定义为源文件中包含的宏名称,则定义 assert 宏 就像

#define assert(ignore) ((void)0)

assert 宏每次都会根据 NDEBUG 的当前状态重新定义 包括<assert.h>

【讨论】:

  • 嗨!如果当我定义 -DNDEBUG 时,仍然调用 assert 会执行某些操作,即 ((void)0),那么这是否会花费最少的 CPU 周期?我认为这只是简单地映射到任何东西,即完全没有代码..不是这样吗?
  • @Abruzzo:直到现在我也这么认为,但是再考虑一下,这会留下一个空的;,如果assertif 内,这可能会出现问题, 例如。我确信编译器会优化像 0; away 这样的行
  • @Abruzzo 和 BTW,检查您的 IDE 或构建系统是否允许您为新项目指定默认模板。然后你可以在每个新项目的发布配置中定义 NDEBUG
  • @Abruzzo 没有代码是什么意思? ((void)0) 在可执行文件中不会生成任何代码。并且该标准要求 assert 可以在任何可以使用 void 类型的表达式的地方使用,因此只需用不使用标记替换它就行了。
  • 编译器在编译时对其进行优化。将其视为 NOP。无用的 NOP 被删除,但这取决于编译器。例如,编译 MIPS 代码时,可能有汇编文件,其中有 NOP,这些 NOP 保留在那里以覆盖分支和加载延迟,以便将指令与时钟循环边界或未定义的行为对齐。
【解决方案3】:

-g标志不影响assert的操作,它只是确保各种调试符号可用。

设置NDEBUG 是禁用断言的标准(如官方、ISO 标准)方式。

【讨论】:

    【解决方案4】:

    您可以通过

    完全禁用断言
    #define NDEBUG
    #include <assert.h>
    

    或者你可以在你的makefile/build过程中设置NDEBUG(通过-DNDEBUG),这取决于你想要一个生产版本还是开发版本。

    【讨论】:

      【解决方案5】:

      是的,使用预处理器/编译器选项-DNDEBUG 在命令行/构建系统上定义NDEBUG

      这与-g插入的调试信息无关。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-09
        • 2016-05-08
        • 1970-01-01
        相关资源
        最近更新 更多