断言失败时如何打印附加信息?

发布于 2024-08-19 19:17:24 字数 303 浏览 8 评论 0原文

如果断言失败,人们通常希望打印出附加信息。一种方法是这样的:

assert(vec.size() > i || 
  !(std::cerr << "False: " << vec.size() << ">" << i))

这样,当 assert 失败时,会打印实际大小。但它很丑陋,而且很容易忘记 ! ,这将使断言条件为真,程序将继续。

人们使用什么来打印有关断言失败的附加信息,就像上面一样?

Often one wants to print out additional information if an assert fails. A way to do that is this:

assert(vec.size() > i || 
  !(std::cerr << "False: " << vec.size() << ">" << i))

This way the actual sizes are printed when the assert fails. But it's ugly, and also it's easy to forget the ! , which will make the assertion condition true and the program will just continue.

What do people use instead to print additional information on assertion failure, like above?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

堇色安年 2024-08-26 19:17:24
#define ASSERT(condition) { if(!(condition)){ std::cerr << "ASSERT FAILED: " << #condition << " @ " << __FILE__ << " (" << __LINE__ << ")" << std::endl; } }

用法:

ASSERT(vec.size()>1);

结果:

ASSERT FAILED: vec.size()>1 @ main.cpp (17)

您可以根据需要将 DebugBreak()exit(-1) 或 waterever 放入宏中。

更新了宏,左侧和右侧分开:

#define ASSERT(left,operator,right) { if(!((left) operator (right))){ std::cerr << "ASSERT FAILED: " << #left << #operator << #right << " @ " << __FILE__ << " (" << __LINE__ << "). " << #left << "=" << (left) << "; " << #right << "=" << (right) << std::endl; } }

用法:

ASSERT(a,>,b);

结果:

ASSERT FAILED: a>b @ assert2.cpp (8). a=3; b=4
#define ASSERT(condition) { if(!(condition)){ std::cerr << "ASSERT FAILED: " << #condition << " @ " << __FILE__ << " (" << __LINE__ << ")" << std::endl; } }

Usage:

ASSERT(vec.size()>1);

Result:

ASSERT FAILED: vec.size()>1 @ main.cpp (17)

You can optionally put DebugBreak() or exit(-1) or watever into the macro, depending on your needs.

Updated macro with separated left and right side:

#define ASSERT(left,operator,right) { if(!((left) operator (right))){ std::cerr << "ASSERT FAILED: " << #left << #operator << #right << " @ " << __FILE__ << " (" << __LINE__ << "). " << #left << "=" << (left) << "; " << #right << "=" << (right) << std::endl; } }

Usage:

ASSERT(a,>,b);

Result:

ASSERT FAILED: a>b @ assert2.cpp (8). a=3; b=4
墨小墨 2024-08-26 19:17:24

人们用什么来打印
有关断言的附加信息
失败,像上面一样?

一般来说,我只是添加一个字符串文字来描述条件的含义:

assert(v.size() > i && "The vector really needs to be larger");

但也许是这样的宏:

#include <cassert>
#include <vector>
#include <iostream>

//#define NDEBUG

#ifndef NDEBUG
#define ASSERT_EX(condition, statement) \
    do { \
        if (!(condition)) { statement; assert(condition); } \
    } while (false)
#else
#define ASSERT_EX(condition, statement) ((void)0)
#endif

int main()
{
    std::vector<int> v;
    unsigned i = 1;
    ASSERT_EX(v.size() > i, std::cerr << "i = " << i << ", v.size() = " << v.size() << '\n');
}

不过,如果 statement 不会有副作用,那么这里会很好,改变如何条件 评估。 :)

What do people use instead to print
additional information on assertion
failure, like above?

Generally I'd just add a string literal describing the meaning of the condition:

assert(v.size() > i && "The vector really needs to be larger");

But perhaps a macro like this:

#include <cassert>
#include <vector>
#include <iostream>

//#define NDEBUG

#ifndef NDEBUG
#define ASSERT_EX(condition, statement) \
    do { \
        if (!(condition)) { statement; assert(condition); } \
    } while (false)
#else
#define ASSERT_EX(condition, statement) ((void)0)
#endif

int main()
{
    std::vector<int> v;
    unsigned i = 1;
    ASSERT_EX(v.size() > i, std::cerr << "i = " << i << ", v.size() = " << v.size() << '\n');
}

Here it would be nice, though, if statement wouldn't have side-effects, changing how condition evaluates. :)

故事和酒 2024-08-26 19:17:24

在许多编译器的发布版本中,assert() 不会编译任何内容。它对生产代码没有任何价值。

我使用这样的结构:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <ctime>
#include <iostream>
using namespace std;


template<typename T> inline bool Verify(T const& t,char const* Expression, char const* File, unsigned long Line)
{
    bool b = !(!t);
    if( b )
        return true;
    // verify failed -- report it 
    std::cerr <<  "Assertion '" << Expression << "' Failed @ " << File << ":" << Line << endl;
    return false;
};

#define verify(exp) (bool)( Verify(exp, #exp, __FILE__, __LINE__) )


template<typename Iter> void doit(Iter const begin, const Iter & end)
{
    for( ; begin != end; ++begin )
        ;
}

int main()
{
    int n = 1;
    n *= 2;
    verify( n == 3 );
    return 0;
}

程序输出:

Assertion 'n == 3' Failed @ .\main.cpp:32

assert() compiles to nothing in Release build of many compilers. It is not something that has any value for production code.

I use a construct like this:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <ctime>
#include <iostream>
using namespace std;


template<typename T> inline bool Verify(T const& t,char const* Expression, char const* File, unsigned long Line)
{
    bool b = !(!t);
    if( b )
        return true;
    // verify failed -- report it 
    std::cerr <<  "Assertion '" << Expression << "' Failed @ " << File << ":" << Line << endl;
    return false;
};

#define verify(exp) (bool)( Verify(exp, #exp, __FILE__, __LINE__) )


template<typename Iter> void doit(Iter const begin, const Iter & end)
{
    for( ; begin != end; ++begin )
        ;
}

int main()
{
    int n = 1;
    n *= 2;
    verify( n == 3 );
    return 0;
}

Program Output:

Assertion 'n == 3' Failed @ .\main.cpp:32
做个少女永远怀春 2024-08-26 19:17:24

大多数扩展断言处理程序的形式如下:

assert_x(CONDITION,EXPLANATION);

您想要的是类似于

assert_args(condition, explanation, ...);

So:

extern string build_assert_string(const string&, explanation, ...);

#define ASSERT_ARGS(CONDITION,build_assert_string EXPLANATION)

call as:

ASSERT_ARGS(x > 0, ("x should be > 0 but it is %d", x));

函数 build_assert_string 是微不足道的。

Most extended assertion handlers are of the form:

assert_x(CONDITION,EXPLANATION);

what you want is something along the lines of

assert_args(condition, explanation, ...);

So:

extern string build_assert_string(const string&, explanation, ...);

#define ASSERT_ARGS(CONDITION,build_assert_string EXPLANATION)

call as:

ASSERT_ARGS(x > 0, ("x should be > 0 but it is %d", x));

The function build_assert_string is trivial.

-黛色若梦 2024-08-26 19:17:24

我觉得下面这句话很有道理。而不是这样:

assert(vec.size() > i || 
  !(std::cerr << "False: " << vec.size() << ">" << i))

只需这样做:

assert(vec.size() > i || 
  assert_msg(vec.size() << ">" << i));

其中 assert_msg 定义如下:

#define assert_msg(x) !(std::cerr << "Assertion failed: " << x << std::endl)

I think the following makes sense. Instead of this:

assert(vec.size() > i || 
  !(std::cerr << "False: " << vec.size() << ">" << i))

just do this:

assert(vec.size() > i || 
  assert_msg(vec.size() << ">" << i));

where assert_msg is defined as something like this:

#define assert_msg(x) !(std::cerr << "Assertion failed: " << x << std::endl)
沉默的熊 2024-08-26 19:17:24

我使用这样的东西:

#define ASSERT(lhs, op, rhs) assert_template((lhs##op##rhs), "(" #lhs #op #rhs ")", lhs, rhs, __FILE__, __LINE__)

template <typename t1, typename t2>
void assert_template(const bool result, const char expr[], t1 lhs, t2 rhs, const char file_name[], const long line_number)
{
    if (!result)
    {
        std::cerr << "Assertion failed";
        std::cerr << "    " << expr;
        std::cerr << "    lhs = " << lhs;
        std::cerr << "    rhs = " << rhs;
        std::cerr << "    File: \"" << file_name << "\"";
        std::cerr << "    Line: " << std::dec << line_number;

        throw "Assertion failed";
    }
};

use 语法有点奇怪,如 ASSERT(vec.size(), >, 1)ASSERT(error, ==, 0)代码>.好处是它还打印出左侧和右侧的值。在 Windows 上,我还喜欢添加 GetLastError() 和 WSAGetLastError()。

I use something like this:

#define ASSERT(lhs, op, rhs) assert_template((lhs##op##rhs), "(" #lhs #op #rhs ")", lhs, rhs, __FILE__, __LINE__)

template <typename t1, typename t2>
void assert_template(const bool result, const char expr[], t1 lhs, t2 rhs, const char file_name[], const long line_number)
{
    if (!result)
    {
        std::cerr << "Assertion failed";
        std::cerr << "    " << expr;
        std::cerr << "    lhs = " << lhs;
        std::cerr << "    rhs = " << rhs;
        std::cerr << "    File: \"" << file_name << "\"";
        std::cerr << "    Line: " << std::dec << line_number;

        throw "Assertion failed";
    }
};

The use syntax is a little weird as in ASSERT(vec.size(), >, 1) or ASSERT(error, ==, 0). The upside is that it also prints out the values of the left and right hand side. On Windows I also like to throw in GetLastError() and WSAGetLastError().

善良天后 2024-08-26 19:17:24

这是我使用的,在失败的实际行上中断,而不是在堆栈的其他地方中断。适用于 MSVC 和 GCC,并使用一点 boost 魔法并生成一个断言对话框:

#include <boost/current_function.hpp>

#if defined(NDEBUG)
# define MY_ASSERT(expr) ((void)0)
#else
    int assertion_failed(char const *expr, char const *function, char const *file, long line);
# if defined(_WIN32)
#  define debugbreak __debugbreak
# else
#  define debugbreak __builtin_trap
# endif
# define MY_ASSERT(expr) ((expr) || !assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) || (debugbreak(), 0))
#endif

#if !defined(NDEBUG)
int assertion_failed(char const *expr, char const *function, char const *file, long line)
{
#if defined(_WIN32)
    return ::_CrtDbgReport(_CRT_ASSERT, file, line, NULL, "%s", expr);
# else
    return !0;
# endif
}
#endif

Here's what I use, breaks on the actual line that failed, rather than elsewhere in the stack. Works on MSVC and GCC, and uses a little boost magic and generates an assertion dialog:

#include <boost/current_function.hpp>

#if defined(NDEBUG)
# define MY_ASSERT(expr) ((void)0)
#else
    int assertion_failed(char const *expr, char const *function, char const *file, long line);
# if defined(_WIN32)
#  define debugbreak __debugbreak
# else
#  define debugbreak __builtin_trap
# endif
# define MY_ASSERT(expr) ((expr) || !assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) || (debugbreak(), 0))
#endif

#if !defined(NDEBUG)
int assertion_failed(char const *expr, char const *function, char const *file, long line)
{
#if defined(_WIN32)
    return ::_CrtDbgReport(_CRT_ASSERT, file, line, NULL, "%s", expr);
# else
    return !0;
# endif
}
#endif
注定孤独终老 2024-08-26 19:17:24

我使用 wxWidgetsif 语句或 wxASSERT_MSG >。

如果您使用框架,请查看它是否提供了一些有用的断言工具。

I use either an if statement or wxASSERT_MSG from wxWidgets.

If you use a framework, see if it provides some useful assertion tools.

£噩梦荏苒 2024-08-26 19:17:24

我根据 Notinlist 答案为纯 C 做了这个(谢谢!):

my_assert.c:

void _assert_int(char *astr, char *oper, char *bstr, int a, int b, char *file, int line) {
  printf("\nAssertion failed: %s %s %s\n%s = %d\n%s = %d\nfile: %s\nline: %d\n", astr, oper, bstr, astr, a, bstr, b, file, line);
  exit(1);
}

void _assert_str_equal(char *vara, char *varb, char *a, char *b, char *file, int line) {

  if (a == b) {
#ifdef TREAT_BOTH_NULL_STRS_AS_ERROR
    if (a != 0) return;
    goto loc_failed;
#else
    return;
#endif
  }

  if ((a == 0) || (b == 0) || (strcmp(a, b) != 0))  {
loc_failed:
    printf("\nAssertion failed: %s == %s\n%s = %s\n%s = %s\nfile: %s\nline: %d\n", vara, varb, vara, a, varb, b, file, line);
    exit(1);
  }

}

my_assert.h:

#define TREAT_BOTH_NULL_STRS_AS_ERROR

#define assert_int(left,operator,right) do { if(!((left) operator (right))) _assert_int(#left, #operator, #right, left, right, __FILE__, __LINE__); } while (0)

#define assert_str_equal(left,right) do { _assert_str_equal(#left, #right, left, right, __FILE__, __LINE__); } while (0)

用法:

assert_int(a,==,b);

assert_str_equal(str1,str2);

同时检查最合适的单元测试框架

I made this for plain C, based on Notinlist answer (thank you!):

my_assert.c:

void _assert_int(char *astr, char *oper, char *bstr, int a, int b, char *file, int line) {
  printf("\nAssertion failed: %s %s %s\n%s = %d\n%s = %d\nfile: %s\nline: %d\n", astr, oper, bstr, astr, a, bstr, b, file, line);
  exit(1);
}

void _assert_str_equal(char *vara, char *varb, char *a, char *b, char *file, int line) {

  if (a == b) {
#ifdef TREAT_BOTH_NULL_STRS_AS_ERROR
    if (a != 0) return;
    goto loc_failed;
#else
    return;
#endif
  }

  if ((a == 0) || (b == 0) || (strcmp(a, b) != 0))  {
loc_failed:
    printf("\nAssertion failed: %s == %s\n%s = %s\n%s = %s\nfile: %s\nline: %d\n", vara, varb, vara, a, varb, b, file, line);
    exit(1);
  }

}

my_assert.h:

#define TREAT_BOTH_NULL_STRS_AS_ERROR

#define assert_int(left,operator,right) do { if(!((left) operator (right))) _assert_int(#left, #operator, #right, left, right, __FILE__, __LINE__); } while (0)

#define assert_str_equal(left,right) do { _assert_str_equal(#left, #right, left, right, __FILE__, __LINE__); } while (0)

usage:

assert_int(a,==,b);

assert_str_equal(str1,str2);

check also the seatest unit test framework

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文