Answers:
_DEBUG
当您指定/MTd
or /MDd
选项时,Visual Studio定义NDEBUG
禁用标准C断言。在适当的时候使用它们,也就是说_DEBUG
,如果你希望你的调试代码必须与一致MS CRT调试技术和NDEBUG
如果你想与其保持一致assert()
。
如果您定义自己的调试宏(并且不修改编译器或C运行时),请避免使用下划线开头名称,因为这些名称是保留的。
NDEBUG是标准的吗?
是的,它是一个标准宏,具有针对C89,C99,C ++ 98,C ++ 2003,C ++ 2011,C ++ 2014标准的语义“不调试”。_DEBUG
标准中没有宏。
C ++ 2003标准将阅读器的“ 17.4.2.1标头”中的“页326”发送给标准C。
NDEBUG类似于。这与标准C库相同。
在C89(C程序员将此标准称为标准C)的“ 4.2诊断”部分中说
http://port70.net/~nsz/c/c89/c89-draft.html
如果在源文件中包含NDEBUG的位置将其定义为宏名,则assert宏的定义如下:
#define assert(ignore) ((void)0)
如果看一下_DEBUG
Visual Studio https://msdn.microsoft.com/zh-cn/library/b0084kay.aspx中的宏
的含义,
就会看到该宏是由您的语言运行库版本选择的。
我依赖NDEBUG
,因为它是唯一一种行为已在整个编译器和实现之间标准化的行为(请参阅有关标准assert宏的文档)。否定逻辑是较小的可读性,但它是您可以快速适应的常见用法。
依赖类似的东西_DEBUG
将依赖于特定编译器和库实现的实现细节。其他编译器可能会或可能不会选择相同的约定。
第三种选择是为项目定义自己的宏,这是很合理的。拥有自己的宏可为您实现各种实现之间的可移植性,并使您可以独立于断言而启用或禁用调试代码。尽管总的来说,我还是建议不要在编译时启用不同类型的调试信息,因为这会导致您不得不构建(和测试)的配置数量增加,从而带来的好处可能很小。
使用这些选项中的任何一个,如果您将第三方代码用作项目的一部分,则必须知道它使用哪种约定。
#if !defined(NDEBUG)
<-@HostileFork不是您的意思吗?#if
不是#ifdef
吗
#ifdef NDEBUG
...,但是请特别注意负逻辑#if !defined(NDEBUG)
。否则,它是一个有点难以赶上在N #ifndef NDEBUG
“
宏NDEBUG
控制assert()
语句是否处于活动状态。
在我看来,这与任何其他调试都是分开的-因此,我使用了除NDEBUG
控制程序中调试信息以外的方法。根据使用的框架,我使用的工具会有所不同。不同的系统具有不同的启用宏,因此我将使用适当的东西。
如果没有框架,我会使用没有下划线的名称。那些往往是为“实现”保留的,我尽力避免名称冲突的问题-当名称是宏时,双倍地出现。
#if
控制的代码放在另一类别中是不同的。 assert(huge_object.IsValid());
可能会很慢,而assert(ptr != nullptr);
事实并非如此。我同意Jonathan的观点,至少在较大的项目中,日志记录和跟踪可能与断言不同,但是我不认为日志记录或跟踪是调试代码,这就是为什么要求澄清的原因。