If you have the code to log_out()
, rewrite it. Most likely, you can do:
static FILE *logfp = ...;
void log_out(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(logfp, fmt, args);
va_end(args);
}
If there is extra logging information needed, that can be printed before or after the message shown. This saves memory allocation and dubious buffer sizes and so on and so forth. You probably need to initialize logfp
to zero (null pointer) and check whether it is null and open the log file as appropriate - but the code in the existing log_out()
should be dealing with that anyway.
The advantage to this solution is that you can simply call it as if it was a variant of printf()
; indeed, it is a minor variant on printf()
.
If you don't have the code to log_out()
, consider whether you can replace it with a variant such as the one outlined above. Whether you can use the same name will depend on your application framework and the ultimate source of the current log_out()
function. If it is in the same object file as another indispensable function, you would have to use a new name. If you cannot work out how to replicate it exactly, you will have to use some variant like those given in other answers that allocates an appropriate amount of memory.
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? */
}
Obviously, you now call the log_out_wrapper()
instead of log_out()
- but the memory allocation and so on is done once. I reserve the right to be over-allocating space by one unnecessary byte - I've not double-checked whether the length returned by vsnprintf()
includes the terminating null or not.