如何完全禁用对assert()的调用?


75

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

如何在编译时完全禁用我的断言?我应该NDEBUG在生产的任何版本中明确定义,而不管它们是调试,发布还是其他任何形式?


1
有点不合理的主题:如果要调试信息,-g则等效于-g2-g3可能会是一个更好的选择,因为它可以提供最多的符号信息。例如,在处-g3,符号#defines将可用。不过,我似乎有些工具链cho之以-g3鼻。同样,许多外部库也依赖于-DDEBUG“调试”构建(Posix仅证明适用-DNDEBUG于“发行”构建)。
jww 2012年

Answers:


94

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


1
必须在之前#include <assert.h>
雷杨

2
@LeiYang似乎必须在last之前添加#include <assert.h>
特朗普2020-正义将于

35

采用 #define NDEBUG

7.2诊断

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

NDEBUG

并未由定义<assert.h>。如果在包含源文件的位置将NDEBUG定义为宏名称,则assert宏的定义简单为

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

断言宏是根据当前的状态定义忠告音响NDEBUG每个时间 <assert.h>被包括。


1
嗨!如果确实是这样,当我定义-DNDEBUG时,仍然要调用assert来执行某些操作,即((void)0),这将花费最少的CPU周期吗?我以为那只是映射为空,即完全没有代码。不是这样吗?
Abruzzo Forte e Gentile

@Abruzzo:直到现在我还是这么认为,但是再三考虑,这会留空;,例如,如果assert在内,则可能会出现问题if。我确信,编译器优化般的线条0;
davka

@Abruzzo和BTW,请检查您的IDE或构建系统是否允许您为新项目指定默认模板。然后,您可以在每个新项目的Release配置中定义NDEBUG
davka 2011年

@Abruzzo没有代码是什么意思?((void)0)不会在可执行文件中生成任何代码。而且该标准要求assert可以在可以使用具有void类型的表达式的任何地方使用,因此仅用无标记替换它就不会起作用。
James Kanze 2011年

编译器会在编译时对其进行优化。将其视为NOP。删除了无用的NOP,但这取决于编译器。例如,在编译MIPS代码时,可能有一个汇编文件,其中的NOP停留在该汇编文件中,以覆盖分支,并将加载延迟加载到需要使指令与时钟循环边界对齐或其他未定义行为的位置。
user2262111 '18

11

您可以通过以下方式完全禁用断言

#define NDEBUG
#include <assert.h>

或者,您可以根据需要生产版本还是开发版本来在makefile / build过程中设置NDEBUG(通过-DNDEBUG)。


10

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

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


4

是的,NDEBUG在命令行/构建系统上使用preprocessor / compiler选项进行定义-DNDEBUG

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.