Есть ли оператор TRACE для базового win32 C++?

В MFC C++ (Visual Studio 6) я привык использовать макрос TRACE для отладки. Есть ли эквивалентное утверждение для простого win32?

7 ответов

Решение

_RPTn прекрасно работает, хотя и не так удобно. Вот некоторый код, который воссоздает оператор MFC TRACE как функцию, допускающую переменное число аргументов. Также добавляет макрос TraceEx, который добавляет исходный файл и номер строки, чтобы вы могли вернуться назад к местоположению оператора.

Обновление: оригинальный код на CodeGuru не будет компилироваться для меня в режиме выпуска, поэтому я изменил способ удаления операторов TRACE для режима выпуска. Вот мой полный источник, который я поместил в Trace.h. Спасибо Томасу Ризосу за оригинал:

// TRACE macro for win32
#ifndef __TRACE_H__850CE873
#define __TRACE_H__850CE873

#include <crtdbg.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#ifdef _DEBUG
#define TRACEMAXSTRING  1024

char szBuffer[TRACEMAXSTRING];
inline void TRACE(const char* format,...)
{
    va_list args;
    va_start(args,format);
    int nBuf;
    nBuf = _vsnprintf(szBuffer,
                   TRACEMAXSTRING,
                   format,
                   args);
    va_end(args);

    _RPT0(_CRT_WARN,szBuffer);
}
#define TRACEF _snprintf(szBuffer,TRACEMAXSTRING,"%s(%d): ", \
                &strrchr(__FILE__,'\\')[1],__LINE__); \
                _RPT0(_CRT_WARN,szBuffer); \
                TRACE
#else
// Remove for release mode
#define TRACE  ((void)0)
#define TRACEF ((void)0)
#endif

#endif // __TRACE_H__850CE873

Также есть OutputDebugString. Однако это не будет удалено при компиляции релиза.

Из документации MSDN, Макросы для отчетности:

Вы можете использовать макросы _RPTn и _RPTFn, определенные в CRTDBG.H, чтобы заменить использование операторов printf для отладки. Эти макросы автоматически исчезают в вашей сборке релиза, когда _DEBUG не определен, поэтому нет необходимости заключать их в #ifdefs.

Я просто использую что-то вроде этого (по памяти, совсем не тестировалось...)

#define TRACE(msg) {\
    std::ostringstream ss; \
    ss << msg << "\n"; \
    OutputDebugString(msg.str()); \
}

И тогда я могу написать такие вещи, как:-

TRACE("MyClass::MyFunction returned " << value << " with data=" << some.data);

Вы можете обернуть это в некоторые #ifdefs, чтобы удалить их в сборках релиза достаточно легко.

Макросы трассировки, которые предоставляют сообщения со ссылкой на исходный код, информацией о стеке вызовов во время выполнения и прототипом функции со значениями параметров:

Extended Trace: Макросы трассировки для Win32

Я обнаружил, что с помощью _RPT() макрос также будет работать с исходным файлом C в Visual Studio 2005. В этой статье отладка с помощью Visual Studio 2005/2008: ведение журнала и трассировка содержит обзор TRACE, _RPT и других макросов типа ведения журнала.

Я генерирую строку для файла журнала, называемого ASSRTLOG, который содержит журналы, и при записи журнала в файл я также делаю следующую строку исходного кода:

_RPT1(_CRT_WARN, "ASSRTLOG: %s", szLog1);

Эта строка помещает тот же журнал, который входит в файл журнала, в окно вывода среды IDE Visual Studio 2005.

Возможно, вас заинтересует механика, лежащая в основе подхода, который мы используем для регистрации. У нас есть функция PifLogAbort() который принимает ряд аргументов, которые затем используются для создания журнала. Эти аргументы включают в себя имя файла, в котором создается журнал, а также номер строки. Макрос выглядит так:

#define NHPOS_ASSERT_TEXT(x, txt) if (!(x)) { PifLogAbort( (UCHAR *)  #x , (UCHAR *)  __FILE__ , (UCHAR *) txt , __LINE__ );}

и прототип функции для PifLogAbort() выглядеть так:

PifLogNoAbort(UCHAR *lpCondition, UCHAR *lpFilename, UCHAR *lpFunctionname, ULONG ulLineNo)

и чтобы использовать макрос, мы вставим такую ​​строку:

NHPOS_ASSERT_TEXT(sBRetCode >= 0, "CliEtkTimeIn():  EtkTimeIn() returned error");

Этот макрос будет делать то, что если код возврата меньше 0 (утверждение не выполняется), будет создан журнал с предоставленным текстом. Журнал включает условие, которое сгенерировало журнал, а также имя файла и номер строки.

Функция PifLogAbort() генерирует журналы указанной длины и обрабатывает выходной файл как кольцевой буфер. Журналы также имеют отметку времени и даты.

В тех случаях, когда мы хотим динамически генерировать описательный текст во время выполнения, возможно, для предоставления действительного значения кода ошибки, мы используем функцию sprintf() с буфером, как в следующей последовательности кода:

if (sErrorSave != STUB_BM_DOWN) {
    char xBuff[128];
    sprintf(xBuff, "CstSendBMasterFH: CstComReadStatus() - 0x%x, sError = %d", usCstComReadStatus, CliMsg.sError);
    NHPOS_ASSERT_TEXT((sErrorSave == STUB_BM_DOWN), xBuff);
}

Если мы хотим, чтобы журналы не генерировались, все, что нам нужно сделать, - это перейти к файлу с одним заголовком, в котором определен макрос, и определить его как ничто, а затем перекомпилировать. Однако мы обнаружили, что эти журналы могут быть очень полезны при исследовании проблем на местах и ​​особенно полезны при интеграционном тестировании.

События Windows являются потенциальной заменой TRACE макросы, в зависимости от вашего конкретного сценария. Код компилируется в конфигурации Debug и Release. Затем трассировку событий можно динамически включать и отключать, отображать в режиме реального времени или выгружать на компьютер клиента для последующей диагностики. Трассировки могут быть соотнесены с информацией трассировки, полученной из других частей ОС.

Если вам просто нужно выгружать информацию всякий раз, когда код достигает определенных контрольных точек, вместе с переменным содержимым, отслеживанием стека или именами вызывающих, то точки отслеживания в Visual Studio являются ненавязчивым вариантом для этого.

Другие вопросы по тегам