Если у вас есть код log_out()
, перепишите его. Скорее всего, вы сможете:
static FILE *logfp = ...;
void log_out(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(logfp, fmt, args);
va_end(args);
}
Если требуется дополнительная информация для регистрации, ее можно распечатать до или после отображаемого сообщения. Это экономит выделение памяти и сомнительные размеры буфера и так далее и так далее. Вероятно, вам нужно инициализировать logfp
нулевое значение (нулевой указатель) и проверить, является ли он нулевым, и при необходимости открыть файл журнала, но код в существующем log_out()
все равно должен иметь дело с этим.
Преимущество этого решения в том, что вы можете просто назвать его, как если бы это был вариант printf()
; действительно, это второстепенный вариант printf()
.
Если у вас нет кода log_out()
, подумайте, можете ли вы заменить его вариантом, подобным описанному выше. Возможность использования того же имени будет зависеть от среды вашего приложения и конечного источника текущей log_out()
функции. Если он находится в том же объектном файле, что и другая незаменимая функция, вам придется использовать новое имя. Если вы не можете понять, как его точно воспроизвести, вам придется использовать какой-то вариант, аналогичный приведенным в других ответах, который выделяет соответствующий объем памяти.
void log_out_wrapper(const char *fmt, ...)
{
va_list args;
size_t len;
char *space;
va_start(args, fmt);
len = vsnprintf(0, 0, fmt, args);
va_end(args);
if ((space = malloc(len + 1)) != 0)
{
va_start(args, fmt);
vsnprintf(space, len+1, fmt, args);
va_end(args);
log_out(space);
free(space);
}
/* else - what to do if memory allocation fails? */
}
Очевидно, что теперь вы вызываете log_out_wrapper()
вместо log_out()
- но выделение памяти и так далее выполняется один раз. Я оставляю за собой право перераспределить пространство на один ненужный байт - я дважды не проверял, vsnprintf()
включает ли длина, возвращаемая с помощью, завершающий нуль или нет.