C ++断言带有时间戳

时间:2013-12-20 11:40:05

标签: c++ assert

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

离。

int a = 10

assert( a > 100 );

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

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

谢谢

1 个答案:

答案 0 :(得分:5)

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:%d\n", \
           #Cond, tbuf##Lin, Fil, Lin);              \
   abort();   }} while(0)
#define tassert(Cond) tassert_at(Cond,__FILE__,__LINE__) 
#endif /*NDEBUG*/

我正在使用cpp concatenation ##Lin一起降低名称冲突的可能性,我正在使用cpp stringification #来制作一个字符串{ {1}}宏观正式。 Cond始终展开,以确保编译器在其中捕获语法错误,即使在Cond tassert作为assert(3)禁用NDEBUG时也是如此。

可以将上述宏中的大多数代码放在某些函数中,例如

 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:%d\n",
            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()要容易得多(用于调试可执行文件的代码的IMHO大小根本不重要;在abort内调用宏中的gdb更加方便 - 缩短回溯并避免一个down命令...)。如果您不想要libc可移植性并且只使用最近的GNU libc,您可以简单地重新定义Glibc特定的__assert_fail函数(请参阅<assert.h>头文件内部)。 YMMV。

BTW,在真正的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);

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