debugging _调试与NDEBUG

aiqt4smr  于 2022-11-14  发布在  其他
关注(0)|答案(7)|浏览(280)

应使用哪个预处理器定义来指定代码的调试部分?
使用#ifdef _DEBUG#ifndef NDEBUG,或者是否有更好的方法,例如#define MY_DEBUG
我认为_DEBUG是Visual Studio特有的,NDEBUG是标准的吗?

s4n0splo

s4n0splo1#

Visual Studio会在您指定/MTd/MDd选项时定义_DEBUGNDEBUG会停用标准C判断提示。请在适当的时候使用它们,例如,如果您希望两柴程式码与MS CRT debugging techniques一致,请使用_DEBUG;如果您希望与assert()一致,请使用NDEBUG
如果您定义了自己的调试宏(并且您没有修改编译器或C运行时),请避免以下划线开头,因为这些是保留名称。

cvxl0en2

cvxl0en22#

NDEBUG是否为标准?
是的,它是一个标准宏,语义为“未调试”,适用于C89、C99、C98、C2003、C2011、C2014标准。标准中没有_DEBUG宏。
C++2003标准将读者在“第326页”处的“17.4.2.1 Headers”发送到标准C。
NDEBUG类似于这与标准C库相同。
在C89(C程序员称此标准为C标准)中的“4.2 DIAGNOSTICS”一节中有人说
https://port70.net/~nsz/c/c89/c89-draft.html
如果在源文件中包含的位置将NDEBUG定义为宏名称<assert.h>,则Assert宏仅定义为

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

如果查看Visual Studio https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros_DEBUG宏的含义,则会发现此宏是由您选择的语言运行库版本自动定义的。

3pvhb19x

3pvhb19x3#

我依赖于NDEBUG,因为它是唯一一个在编译器和实现中行为标准化的(参见标准assert宏的文档)。负逻辑是一个小的可读性障碍,但它是一个常见的习惯用法,您可以很快适应它。
依赖于_DEBUG这样的东西就是依赖于特定编译器和库实现的实现细节。其他编译器可能会也可能不会选择相同的约定。
第三种选择是为项目定义自己的宏,这是非常合理的。拥有自己的宏可以在实现之间提供可移植性,并允许您独立于Assert启用或禁用调试代码。尽管如此,一般来说,我建议不要在编译时启用不同类的调试信息,因为它会导致您必须构建(和测试)的配置数量的增加,而这一点可以说是微不足道的。
使用这些选项中的任何一个时,如果您使用第三方代码作为项目的一部分,则必须了解它使用的约定。

lkaoscv7

lkaoscv74#

NDEBUG控制assert()语句是否处于活动状态。
在我看来,这是独立于任何其他调试的--所以我使用NDEBUG以外的东西来控制程序中的调试信息。不同的系统有不同的启用宏,我使用任何合适的宏。
如果没有框架,我会使用没有前导下划线的名称;这些都倾向于保留给“实现”,我试图避免名称冲突的问题--当名称是宏时更是如此。

bksxznpy

bksxznpy5#

保持一致性,不管是哪一个。而且,如果出于某种原因,你必须使用某个DEBUG标识符与另一个程序或工具互操作,这很容易做到

#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa
mzmfm0qo

mzmfm0qo6#

不幸的是,DEBUG过载严重。例如,建议总是为RELEASE版本生成并保存一个pdb文件。这意味着-Zx标志之一,以及-DEBUG链接器选项。而_DEBUG与运行时库的特殊调试版本有关,如对mallocfree的调用。那么NDEBUG将禁用Assert。

ujv3wf0j

ujv3wf0j7#

不管名称如何,NDEBUG与您是否创建调试版本无关,它控制Assert是否(assert())是活动的还是不活动的。我不会基于它做任何其他的事情,因为您有时可能希望拥有不带Assert的调试版本或带有Assert的发布版本,然后必须相应地设置NDEBUG,但这并不这并不意味着您还希望调试或发布所有其他代码。
从编译器的Angular 来看,调试版本是不存在的。你告诉编译器用一组特定的设置来编译代码,如果你想对不同类型的版本使用不同的设置,那么这实际上是你自己创造的,编译器对此一无所知。你实际上可能有50种不同的构建风格,而不仅仅是发布和调试(profile、test、deploy等),所以如何在你自己的代码中标识这些样式取决于你。如果你需要这些样式的预处理器标记,你可以定义它们的命名方式,并且相同的命名空间规则适用于你在代码中定义的所有其他样式。

相关问题