带时间戳的 C++ 断言

标签 c++ assert

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

例如

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:%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 #Cond 制作一个字符串宏正式。 Cond始终展开,以确保即使禁用 tassert 编译器也能捕获其中的语法错误与 NDEBUG作为assert(3)

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

 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()在宏中调用要容易得多(恕我直言,用于调试可执行文件的代码大小根本无关紧要;在宏中调用 abortgdb 内部更方便 - 缩短回溯并避免一个 down 命令.. .).如果你不想libc便携性,只需使用最新的 GNU libc您可以简单地重新定义 Glibc 特定的 __assert_fail函数(参见内部 <assert.h> 头文件)。 YMMV.

顺便说一句,在实际的 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);

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

关于带时间戳的 C++ 断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20702852/

相关文章:

C++ 对象不止一次被销毁

c++ - 带有 CDT 的 Visual C++ 2008 Express 或 Eclipse Ganymede

c++ -/usr/bin/ld : cannot find

Python assert_call_with,有通配符吗?

c# - 不使用 lambda 表达式进行断言时 NUnit 测试失败

c++ - GCCs atomic builtins - 支持哪些处理器

c++ - 尝试在 Linux 上运行 OpenGL,拥有必要的库但无法运行? (C++)

python - 什么时候应该在 Python 中使用 'assert'?

xquery - 如何使用 SOAP UI Xquery Matches 获取某些预期值

c# - 打印断言错误后使应用程序正常关闭