Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Как создать функцию только для отладки,которая принимает список переменных аргументов? Как printf()
Я хотел бы сделать функцию ведения журнала отладки с теми же параметрами, что и printf . Но тот, который может быть удален препроцессором во время оптимизированных сборок.
Например:
Debug_Print("Warning: value %d > 3!\n", value);
Я посмотрел на variadic macros, но они доступны не на всех платформах. gcc поддерживает их, msvc -нет.
Я все еще делаю это старым способом, определяя макрос (XTRACE, ниже), который коррелирует либо с no-op, либо с вызовом функции со списком переменных аргументов. Внутренне, вызов vsnprintf, так что вы можете сохранить синтаксис printf :
#include <stdio.h>
void XTrace0(LPCTSTR lpszText)
{
::OutputDebugString(lpszText);
}
void XTrace(LPCTSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
int nBuf;
TCHAR szBuffer[512]; // get rid of this hard-coded buffer
nBuf = _vsnprintf(szBuffer, 511, lpszFormat, args);
::OutputDebugString(szBuffer);
va_end(args);
}
Затем типичный переключатель #ifdef:
#ifdef _DEBUG
#define XTRACE XTrace
#else
#define XTRACE
#endif
Ну, это можно почистить совсем немного, но это основная идея.
Вот как я делаю отладочные распечатки в C++. Определите 'dout' (debug out) следующим образом:
#ifdef DEBUG
#define dout cout
#else
#define dout 0 && cout
#endif
В коде я использую 'dout' так же, как и 'cout'.
dout << "in foobar with x= " << x << " and y= " << y << '\n';
Если препроцессор заменяет 'dout' на '0 && cout', обратите внимание, что << имеет более высокий приоритет, чем &&, и при коротком замыкании && вся строка будет оценена как 0. Поскольку 0 не используется, компилятор вообще не генерирует код для этой строки.
Вот что я делаю в C/C++. во-первых, вы пишете функцию, которая использует материал varargs (см. ссылку в публикации Стью). Тогда сделай что-нибудь вроде этого:
int debug_printf( const char *fmt, ... );
#if defined( DEBUG )
#define DEBUG_PRINTF(x) debug_printf x
#else
#define DEBUG_PRINTF(x)
#endif
DEBUG_PRINTF(( "Format string that takes %s %s\n", "any number", "of args" ));
Все, что вам нужно помнить, это использовать двойные парены при вызове функции отладки, и вся строка будет удалена в коде без DEBUG.
@CodingTheWheel:
Есть одна небольшая проблема с вашим подходом. Рассмотрим такой вызов, как
XTRACE("x=%d", x);
Это прекрасно работает в отладочной сборке, но в сборке выпуска она расширится до:
("x=%d", x);
Который является совершенно законным C и будет компилироваться и обычно запускаться без побочных эффектов, но генерирует ненужный код. Подход, который я обычно использую для устранения этой проблемы, заключается в следующем:
Пусть функция XTrace возвращает значение int (просто верните 0, возвращаемое значение не имеет значения)
Измените значение #define в предложении #else на:
0 && XTrace
Теперь версия релиза будет расширена до:
0 && XTrace("x=%d", x);
и любой приличный оптимизатор выбросит все это, так как оценка короткого замыкания предотвратила бы что-либо после &&, которое когда-либо будет выполнено.
Конечно, как только я написал это последнее предложение, я понял, что, возможно, исходная форма тоже может быть оптимизирована, и в случае побочных эффектов, таких как вызовы функций, передаваемые в качестве параметров в XTrace, это может быть лучшим решением, так как оно гарантирует, что отладочные и выпускные версии будут вести себя одинаково.
В C++ вы можете использовать оператор потоковой передачи для упрощения вещей:
#if defined _DEBUG
class Trace
{
public:
static Trace &GetTrace () { static Trace trace; return trace; }
Trace &operator << (int value) { /* output int */ return *this; }
Trace &operator << (short value) { /* output short */ return *this; }
Trace &operator << (Trace &(*function)(Trace &trace)) { return function (*this); }
static Trace &Endl (Trace &trace) { /* write newline and flush output */ return trace; }
// and so on
};
#define TRACE(message) Trace::GetTrace () << message << Trace::Endl
#else
#define TRACE(message)
#endif
и использовать его, как:
void Function (int param1, short param2)
{
TRACE ("param1 = " << param1 << ", param2 = " << param2);
}
Затем вы можете реализовать настраиваемый вывод trace для классов во многом таким же образом, как и для вывода в std::cout .
Ах, vsprintf() был, что я был пропавших без вести. Я могу использовать это для передачи списка переменных аргументов непосредственно в printf():
#include <stdarg.h>
#include <stdio.h>
void DBG_PrintImpl(char * format, ...)
{
char buffer[256];
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
printf("%s", buffer);
va_end(args);
}
Затем оберните все это в макрос.
На каких платформах они недоступны? включаемом файле stdarg является частью стандартной библиотеки:
http://www.opengroup.org/onlinepubs/009695399/basedefs/stdarg.h.html
Любая платформа, не обеспечивающая этого, не является стандартной реализацией C (или очень, очень старой). Для этого вам придется использовать varargs:
http://opengroup.org/onlinepubs/007908775/xsh/varargs.h.html
Часть проблемы с такого рода функциональностью заключается в том, что часто она требует вариативная macros. Они были стандартизированы совсем недавно(C99), и многие из них были стандартизированы совсем недавно. старые компиляторы C не поддерживают стандарт или имеют свою собственную специальную работу вокруг.
Ниже приведен отладочный заголовок, который я написал и который имеет несколько интересных функций:
- Поддерживает синтаксис C99 и C89 для debug macros
- Включение / выключение вывода на основе аргумента функции
- Вывод в файловый дескриптор(file io)
Примечание: по какой-то причине у меня были некоторые небольшие проблемы с форматированием кода.
#ifndef _DEBUG_H_
#define _DEBUG_H_
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "stdarg.h"
#include "stdio.h"
#define ENABLE 1
#define DISABLE 0
extern FILE* debug_fd;
int debug_file_init(char *file);
int debug_file_close(void);
#if HAVE_C99
#define PRINT(x, format, ...) \
if ( x ) { \
if ( debug_fd != NULL ) { \
fprintf(debug_fd, format, ##__VA_ARGS__); \
} \
else { \
fprintf(stdout, format, ##__VA_ARGS__); \
} \
}
#else
void PRINT(int enable, char *fmt, ...);
#endif
#if _DEBUG
#if HAVE_C99
#define DEBUG(x, format, ...) \
if ( x ) { \
if ( debug_fd != NULL ) { \
fprintf(debug_fd, "%s : %d " format, __FILE__, __LINE__, ##__VA_ARGS__); \
} \
else { \
fprintf(stderr, "%s : %d " format, __FILE__, __LINE__, ##__VA_ARGS__); \
} \
}
#define DEBUGPRINT(x, format, ...) \
if ( x ) { \
if ( debug_fd != NULL ) { \
fprintf(debug_fd, format, ##__VA_ARGS__); \
} \
else { \
fprintf(stderr, format, ##__VA_ARGS__); \
} \
}
#else /* HAVE_C99 */
void DEBUG(int enable, char *fmt, ...);
void DEBUGPRINT(int enable, char *fmt, ...);
#endif /* HAVE_C99 */
#else /* _DEBUG */
#define DEBUG(x, format, ...)
#define DEBUGPRINT(x, format, ...)
#endif /* _DEBUG */
#endif /* _DEBUG_H_ */
Столкнувшись с этой проблемой сегодня, мое решение заключается в следующем макро:
static TCHAR __DEBUG_BUF[1024]
#define DLog(fmt, ...) swprintf(__DEBUG_BUF, fmt, ##__VA_ARGS__); OutputDebugString(__DEBUG_BUF)
Затем вы можете вызвать функцию следующим образом:
int value = 42;
DLog(L"The answer is: %d\n", value);
Вот что я использую:
inline void DPRINTF(int level, char *format, ...)
{
# ifdef _DEBUG_LOG
va_list args;
va_start(args, format);
if(debugPrint & level) {
vfprintf(stdout, format, args);
}
va_end(args);
# endif /* _DEBUG_LOG */
}
который абсолютно ничего не стоит во время выполнения, когда флаг _DEBUG_LOG выключен.
Это версия ответа пользователя TCHAR, поэтому он будет работать как ASCII (обычный) или режим Unicode (более или менее).
#define DEBUG_OUT( fmt, ...) DEBUG_OUT_TCHAR( \
TEXT(##fmt), ##__VA_ARGS__ )
#define DEBUG_OUT_TCHAR( fmt, ...) \
Trace( TEXT("[DEBUG]") #fmt, \
##__VA_ARGS__ )
void Trace(LPCTSTR format, ...)
{
LPTSTR OutputBuf;
OutputBuf = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, \
(size_t)(4096 * sizeof(TCHAR)));
va_list args;
va_start(args, format);
int nBuf;
_vstprintf_s(OutputBuf, 4095, format, args);
::OutputDebugString(OutputBuf);
va_end(args);
LocalFree(OutputBuf); // tyvm @sam shaw
}
Я говорю "более или менее", потому что он не будет автоматически преобразовывать аргументы ASCII string в WCHAR, но он должен помочь вам выйти из большинства проблем Юникода, не беспокоясь о том, чтобы обернуть строку формата в TEXT() или предшествовать ей с помощью L.
В основном производные от MSDN: извлечение кода последней ошибки