ASSERT也适用于发布模式

ASSERT that works on Release mode too?

本文关键字:模式 布模式 适用于 ASSERT      更新时间:2023-10-16

我在哪里可以找到一个ASSERT类似于assert(...)宏从标准c++库(在<cassert>中定义的一个),但这适用于发布模式?或者我该怎么写呢?

我喜欢assert(...),因为它会自动打印源文件中断言失败的行,以及断言表达式。我希望这些功能(如果可能的话)也出现在ASSERT发布模式中。

基本上assert是一个宏,计算表达式,如果它失败打印一些东西,然后abort s。写一些类似的东西并不难,比如。

#define ASSERT(x) do { if( !(x) ) { printfunc( #x ); abort(); } while(0)

然后您可以修改它以满足您的要求。例如,您可能不希望在发布模式下执行abort。您还可以调整您的打印输出(只包括您认为有用的信息),为了获得文件和行信息,您将使用__FILE____LINE__宏(顺便说一句,定义中的#x扩展为包含表达式x的字符串文字)。

在发布版本中,不要定义NDEBUG, assert就可以了

可以不定义NDEBUG

#undef NDEBUG

靠近assert语句

或者您可以定义自己的assert

#define assert(x) printf(...)

根据这篇文章,我也推出了自己的断言,总是在发布模式下触发:

这是它的GIST,我没有提供(AbstractAsserter的实际实现,它基于文章),但是您可以理解:

#include <iostream>
struct AbstractAsserter
{
    virtual void doAssert(const char* expr, const char* file, int line, const char* function) const
    {
        std::cout << "Asserting now at " << expr << ", " << file << ", " << line << ", " << function << std::endl;
    }
};
struct Local
{
  const char* function_;
  const char* expr_;
  const char* file_;
  int line_;
  Local( const char* f, const char* ex, const char* file, int line )
  : function_( f ), expr_( ex ), file_( file ), line_( line )
  { }
  Local operator << ( const AbstractAsserter& impl )
  {
    impl.doAssert( expr_, file_, line_, function_ );
    return *this;
  }
};
// More to be added as required...
#if defined( __GNUC__ )
# define WE_FUNCTION __PRETTY_FUNCTION__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
# define WE_FUNCTION __func__
#else
# define WE_FUNCTION "null_func()"
#endif

#define WE_ASSERT( expr )
  if( expr );
  else Local( WE_FUNCTION, #expr, __FILE__, __LINE__ )
    << AbstractAsserter();

int main() {
    WE_ASSERT(!"bad BAD BOY!");
    return 0;
}

有了这个结构,你的实现也可以做一些关键的状态保存等(如果你认为你的程序状态是可信的…有争议的)。

在发布模式下使用std assert(根据注释,您希望启用编译器优化)本身并不是问题,正如其他答案所确定的那样。写一个自定义的已经完成了,所以没有太大的问题。

然而,引用Dr. Dobb的文章:

在你的代码中自由使用断言;他们是警惕的、可靠的守卫,保护你(你的程序)不疯狂

如果您担心断言+编译器优化,那么这两件事在概念上有点增加的可能性:

  • assert应该而且可以自由使用,目的是尽早发现bug,而主要是,这样assert代码是否会损害性能就无关紧要了。
  • 如果你想/需要运行优化,你可能不喜欢额外的(现在优化,但仍然)断言代码给你的性能打击。
所以,总的来说,我看到了释放模式断言的使用,但要确保将它与"正常"断言分开。