1

我们的应用程序似乎出现了一种奇怪的情况。一个 ASSERT 被触发,它应该只在定义了 _DEBUG 的情况下运行,但是当应用程序在发布模式下编译时它正在被评估。

ASSERT 定义在一个头文件中,并被另一个头文件触发,该头文件包含在源文件中。

进一步检查,源文件确实在发布模式下运行(_DEBUG 未定义,NDEBUG 已定义)。但是,头文件定义了 _DEBUG,而不是 NDEBUG。

按照传统观念,#include 一个头文件就等于将代码行剪切并粘贴到源文件中。这将使上述行为成为不可能。

我们正在 VS2010 中编译一个大型的混合语言(英特尔 FORTRAN 和 C++)应用程序。不过,这个问题也出现在我们的构建服务器上,所以它似乎不仅仅是 VS2010 的“功能”。

我们检查了:

  1. 所有项目都在 Release 中构建。
  2. 受影响的 cpp 文件没有设置任何异常属性。
  3. 我们的解决方案中没有手动定义或取消定义 _DEBUG 或 NDEBUG 的文件。
  4. 我们通过包含以下条款来确立上述行为:

bool is_debug = false;

#ifdef _DEBUG

is_debug = true

#endif

并在之后立即打破这一点。

我们要测试的东西已经不多了——我什至可以假设的唯一事情是:

  1. 某些标准库或外部包含正在重新定义 _DEGUG 和 NDEBUG,或者
  2. 某些东西覆盖了#include 宏(这可能吗?)。

编辑 - - - - - - - - - - - - - - - - - - - - - - - - - ---------

部分感谢#error 技巧(如下),我们发现了直接的问题:在几个项目中,NDEBUG 和_DEBUG 不再定义。所有这些项目都意味着从宏 $(PreprocessorDefinitions) 继承了一些东西——但这并没有在任何地方定义。

这仍然留下了一些尴尬的问题:

  1. 导致上述行为的源文件确实在其项目设置中定义了 NDEBUG,但它们包含的头文件没有(尽管 VS2010 确实将正确的 #ifdef 块灰显)。
  2. 如果 PreprocessorDefinitions 宏被所有 C++ 项目(它似乎是)继承,那么为什么不在任何地方定义它?
4

3 回答 3

2

对于此类问题,我通常采用的方法是查看符号的定义或#ifdef使用的位置,然后将“#error Some text”放入其中。这样编译过程就会中断,而不必等待并运行它。然后你可以看到真正定义了什么。

您还可以在断言发生的地方添加这样的#ifdef - #error 组合,然后您可以绝对确定编译器认为什么应该是有效的。

于 2013-06-11T11:32:58.313 回答
0

OK, the problem turns out to be because NDEBUG and _DEBUG are missing from the Properties->C/C++->Preprocessor->Preprocessor Definitions on several projects. Whether they were always missing, or whether they had originally been included via the $(PreprocessorDefinitions) macro is unclear.

Thanks to @Lamza, @Devolus and @Werner Henze - all of their input was useful, and the eventual problem was depressingly mundane.

于 2013-06-11T14:39:24.160 回答
0

来自http://msdn.microsoft.com/en-us/library/9sb57dw4(v=vs.71).aspx

断言例程在 C 运行时库的发行版和调试版中都可用。另外两个断言宏 _ASSERT 和 _ASSERTE 也可用,但它们仅在定义 _DEBUG 标志时评估传递给它们的表达式。

换句话说:要么使用 _ASSERT(...) 要么 #define NDEBUG,所以你不会在发布版本中得到断言。

于 2013-06-11T11:36:07.817 回答