Есть ли оператор 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, чтобы удалить их в сборках релиза достаточно легко.
Макросы трассировки, которые предоставляют сообщения со ссылкой на исходный код, информацией о стеке вызовов во время выполнения и прототипом функции со значениями параметров:
Я обнаружил, что с помощью _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 являются ненавязчивым вариантом для этого.