如果assert
失败,通常会想要打印其他信息。一种方法是:
assert(vec.size() > i ||
!(std::cerr << "False: " << vec.size() << ">" << i))
这样,assert
失败时会打印实际尺寸。但它很丑陋,也很容易忘记!
,这将使断言条件成立,程序将继续。
人们使用什么来打印关于断言失败的其他信息,如上所述?
答案 0 :(得分:11)
#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)
或watever放入宏中。
已更新宏,左右分开:
#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
答案 1 :(得分:5)
人们使用什么来打印 有关断言的其他信息 失败,如上所述?
通常我只是添加一个描述条件含义的字符串文字:
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
不会产生副作用,则会改变condition
的评估方式,这样会很不错。 :)
答案 2 :(得分:3)
assert()在许多编译器的Release版本中编译为零。它不是对生产代码有任何价值的东西。
我使用这样的结构:
#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
答案 3 :(得分:1)
大多数扩展断言处理程序的格式为:
assert_x(CONDITION,EXPLANATION);
你想要的是
assert_args(condition, explanation, ...);
所以:
extern string build_assert_string(const string&, explanation, ...);
#define ASSERT_ARGS(CONDITION,build_assert_string EXPLANATION)
致电:
ASSERT_ARGS(x > 0, ("x should be > 0 but it is %d", x));
函数build_assert_string很简单。
答案 4 :(得分:1)
我认为以下内容是有道理的。而不是:
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)
答案 5 :(得分:0)
我使用这样的东西:
#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";
}
};
使用语法有点奇怪,如ASSERT(vec.size(), >, 1)
或ASSERT(error, ==, 0)
。好处是它还打印出左侧和右侧的值。在Windows上我还想抛出GetLastError()和WSAGetLastError()。
答案 6 :(得分:0)
这是我使用的,打破了失败的实际行,而不是堆栈中的其他地方。适用于MSVC和GCC,并使用一点提升魔法并生成一个断言对话框:
#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
答案 7 :(得分:0)
我使用来自wxWidgets的if
语句或wxASSERT_MSG。
如果您使用框架,请查看它是否提供了一些有用的断言工具。
答案 8 :(得分:0)
我根据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);
还检查最新的单元测试框架
答案 9 :(得分:0)
用“fprintf”替换std::cerr怎么样? “fprintf”返回打印的字符数(成功时> = 0),您可以像这样使用它(非常容易记住和清晰阅读......至少对我来说):
assert(vec.size() > i || (fprintf(stderr, "False: %d > %d\n", vec.size(), i) >= 0);
为了方便起见,您可以将其设为内联函数(在 C 中),将其命名为“assert_vecSize_largerThan(...)”。