应该使用哪个预处理器定义来指定代码的调试部分?
使用#ifdef _DEBUG
或#ifndef NDEBUG
或者有更好的方法,例如#define MY_DEBUG
?
我认为_DEBUG
是Visual Studio特有的,是NDEBUG标准吗?
答案 0 :(得分:106)
当您指定_DEBUG
或/MTd
选项时,Visual Studio定义/MDd
,NDEBUG
禁用标准C断言。如果您希望调试代码与MS CRT debugging techniques和_DEBUG
一致,如果您希望与NDEBUG
保持一致,请在适当时使用它们,即assert()
。
如果您定义自己的调试宏(并且不破解编译器或C运行时),请避免使用下划线开始名称,因为这些是保留的。
答案 1 :(得分:39)
我依赖NDEBUG
,因为它是唯一一个在编译器和实现之间标准化的行为(请参阅标准断言宏的文档)。负逻辑是一个小的可读性speedbump,但它是你可以快速适应的常用习惯。
依赖于_DEBUG
之类的东西将依赖于特定编译器和库实现的实现细节。其他编译器可能会也可能不会选择相同的约定。
第三个选项是为您的项目定义自己的宏,这是非常合理的。拥有自己的宏可以实现跨实现的可移植性,它允许您独立于断言启用或禁用调试代码。虽然,一般来说,我建议不要在编译时启用不同类别的调试信息,因为它会导致您必须构建(和测试)的配置数量增加,这可能会带来很小的好处。
使用这些选项中的任何一个,如果您将第三方代码用作项目的一部分,则必须了解它使用的约定。
答案 2 :(得分:36)
NDEBUG标准吗?
是的,它是C89,C99,C ++ 98,C ++ 2003,C ++ 2011,C ++ 2014标准的语义“Not Debug”的标准宏。标准中没有_DEBUG
个宏。
C ++ 2003标准发送阅读器“第326页”“17.4.2.1标题” 标准C.
NDEBUG类似,因为它与标准C库相同。
在C89(C程序员将此标准称为标准C)中的“4.2诊断”一节中有人说
http://port70.net/~nsz/c/c89/c89-draft.html
如果NDEBUG被定义为源文件中的宏名称 在包含的地方,断言宏被简单地定义为
#define assert(ignore) ((void)0)
如果在Visual Studio中查看_DEBUG
宏的含义
https://msdn.microsoft.com/en-us/library/b0084kay.aspx
然后可以看出,这个宏是由你的语言运行时库版本自动定义的。
答案 3 :(得分:13)
宏NDEBUG控制assert()语句是否处于活动状态。
在我看来,这与其他任何调试都是分开的 - 所以我使用NDEBUG以外的东西来控制程序中的调试信息。根据我正在使用的框架,我使用的内容各不相同;不同的系统有不同的启用宏,我使用任何适当的。
如果没有框架,我会使用没有前导下划线的名称;那些往往被保留给'实现',我试图避免名字collsions的问题 - 当名称是一个宏时,加倍。
答案 4 :(得分:6)
保持一致,哪一个无关紧要。此外,如果由于某种原因你必须使用某个DEBUG标识符与另一个程序或工具互操作,那么很容易做到
#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa
答案 5 :(得分:3)
不幸的是“DEBUG”严重超载。例如,建议始终为RELEASE构建生成并保存pdb文件。这意味着-Zx标志之一和-DEBUG链接器选项。而_DEBUG与运行时库的特殊调试版本有关,例如对malloc和free的调用。然后NDEBUG将禁用断言。