C++使用时间戳断言

C++ assert with time stamp

本文关键字:断言 时间戳 C++      更新时间:2023-10-16

是否可以在断言失败时记录带有时间戳的信息

前任。

int a = 10
assert( a > 100 );

然后它将失败并输出,就像时间戳一样

2013-12-02 , 17:00:05 assert failed !! (a > 100) line : 22

谢谢

assert

是一个宏(它必须是一个宏,以提供__LINE____FILE__信息)。

您可以定义自己的定义。出于可读性的原因,我会将其命名为tassert,也许像(未经测试的代码)

#ifdef NDEBUG
#define tassert(Cond) do {if (0 && (Cond)) {}; } while(0)
#else
#define tassert_at(Cond,Fil,Lin) do { if ((Cond)) {  
time_t now##Lin = time(NULL);                     
char tbuf##Lin [64]; struct tm tm##Lin;           
localtime_r(&now##Lin, &tm##Lin);                 
strftime (tbuf##Lin, sizeof(tbuf##Lin),           
"%Y-%m-%d,%T", &tm##Lin);               
fprintf(stderr, "tassert %s failure: %s %s:%dn", 
#Cond, tbuf##Lin, Fil, Lin);              
abort();   }} while(0)
#define tassert(Cond) tassert_at(Cond,__FILE__,__LINE__) 
#endif /*NDEBUG*/

我正在使用 cpp 连接##Lin来降低名称冲突的可能性,并且我正在使用 cpp 字符串化#将字符串从Cond宏形式中制作出来。Cond总是展开的, 以确保编译器捕获其中的语法错误, 即使像 assert(3) 那样使用NDEBUG禁用tassert

可以将上述宏中的大部分代码放在某个函数中,例如

void tassert_at_failure (const char* cond, const char* fil, int lin) {
timer_t now = time(NULL);
char tbuf[64]; struct tm tm;
localtime_r (&now, &tm);
strftime (tbuf, sizeof(tbuf), "%Y-%m-%d,%T", &tm);
fprintf (stderr, "tassert %s failure: %s %s:%dn",
cond, tbuf, fil, lin);
abort();
}

然后只是定义(有点像<assert.h>...

#define tassert_at(Cond,Fil,Lin) do { if ((Cond)) {  
tassert_at_failure(#Cond, Fil, Lin); }} while(0)

但我不太喜欢这种方法,因为对于使用gdb进行调试,在宏中调用abort()要容易得多(恕我直言,用于调试可执行文件的代码大小根本不重要;在宏中调用abort在宏中更方便gdb- 进行更短的回溯并避免一个down命令......如果你不想要libc可移植性,而只是使用最新的GNUlibc你可以简单地重新定义Glibc特定的__assert_fail函数(见<assert.h>头文件内部)。扬子晚报.

顺便说一句,在实际C++代码中,我更喜欢将<<用于类似断言的调试输出。这允许使用我自己的operator <<输出例程(如果您将其作为额外的宏参数提供),所以我正在考虑(未经测试的代码!

#define tassert_message_at(Cond,Out,Fil,Lin)         
do { if ((Cond)) {                                  
time_t now##Lin = time(NULL);                     
char tbuf##Lin [64]; struct tm tm##Lin;           
localtime_r(&now##Lin, &tm##Lin);                 
strftime (tbuf##Lin, sizeof(tbuf##Lin),           
"%Y-%m-%d,%T", &tm##Lin);               
std::clog << "assert " << #Cond << " failed "     
tbuf##Lin << " " << Fil << ":" << Lin   
<< Out << std::endl;                    
abort (); } } while(0)
#define tassert_message(Cond,Out) 
tassert_message_at(Cond,Out,__FILE__,__LINE__)

然后我会使用tassert_message(i>5,"i=" << i);

顺便说一句,你可能想在tassert_at宏中使用 syslog(3) 而不是fprintf