也适用于发布模式的ASSERT?

时间:2015-08-21 14:25:07

标签: c++ std assert

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

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

5 个答案:

答案 0 :(得分:3)

基本上assert是一个用于评估表达式的宏,如果失败则打印一些内容然后abort s。编写类似的东西并不难,比如。

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

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

答案 1 :(得分:2)

在发布版本中,不要定义NDEBUGassert也可以。

答案 2 :(得分:1)

您可以取消定义NDEBUG

#undef NDEBUG

在断言声明附近

或者您可以定义自己的断言

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

答案 3 :(得分:0)

我已经推出了自己的断言,它总是在发布模式下启动,基于此article

这是它的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;
}

使用这种结构,你的实现也可以做一些关键的状态保存等(如果你认为你的程序状态值得信赖......有争议)。

答案 4 :(得分:0)

在发布模式下使用std assert(通过注释,您希望启用编译器优化)本身并不是问题,正如其他答案所证实的那样。编写自定义脚本已经完成,因此那里没有太多问题。

但是,引用Dr. Dobb's article

  

在整个代码中随意使用断言;他们是警惕,可靠的守卫,可保护您(您的程序)免于精神错乱

如果您担心需要使用断言和编译器优化,那么从概念上来说,这两件事有点增加几率:

  • 应该并且可以广泛使用Asserts,目的是尽早发现错误,而主要是,因此断言代码是否会损害性能无关紧要。
  • 如果您希望/需要进行优化,则可能不希望性能达到额外的(现已优化,但仍然)断言代码为您带来的效果。

因此,总而言之,我看到了释放模式断言的使用,但请确保将其与“正常”断言分开,在大多数人会认为“正常”断言处于释放模式的情况下。