2013-12-20 3 views
3

- это возможность записи информации, когда assert не удалось с отметкой времениC++ утвердить с отметкой времени

ex.

int a = 10 

assert(a > 100); 

тогда будет провалена и выход так же, как с временной меткой, а

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

Спасибо

+6

оберните свой собственный ASSERT сверху утверждения и запишите время журнала – billz

ответ

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# сделать строку из of 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() вызывается в макросе намного проще (размер кода IMHO для отладки исполняемых файлов вообще не имеет значения, вызов abort в макросе намного удобнее внутри gdb - создание более коротких обратных трасс и исключение одной команды down ...). Если вы не хотите переносить мобильность libc и используете только последний GNU libc, вы можете просто переопределить функцию __assert_fail Glibc (см. Внутри заголовочный файл <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);

BTW, вам возможно, захотите использовать syslog(3) вместо fprintf в вашем tassert_at макросе.

+0

Почему так много кода в макросе. Все макросы должны делать в случае сбоя вызов функции assertion_failed, с информацией, которая не может быть немедленно получена внутри функции. –

+0

Я добавил больше текста, чтобы объяснить, что .... –

Смежные вопросы