Reputation: 463
I have a class:
FILE *logFile = fopen("out.log", "w");
class Log {
public:
static void d(const char *message, ...) __attribute__((format (printf, 1, 2)));
}
In source file:
void Log::d(const char *message, ...) {
va_list argptr;
va_start(argptr, message);
vprintf(message, argptr);
printf("\n");
fflush(stdout);
if (logFile) {
vfprintf(logFile, message, argptr);
fprintf(logFile, "\n");
fflush(logFile);
}
va_end(argptr);
}
But when I call for example Log::d("test %d %s %f", 10, "str", 0.1);
it prints test 0 @WAíõ 0,000000
to the file.
What's wrong?
Upvotes: 2
Views: 1907
Reputation: 5630
The problem is that you are using your va_list
argptr
2 times. Once in the vprintf
and secondly in the vfprintf
call. How a va_list
works with the stack is implementation defined, see here. The va_list
type for example is implemented in Linux x86_64 like said here on SO:
The va_list Type
The va_list type is an array containing a single element of one structure containing the necessary information to implement the va_arg macro. The C definition of va_list type is given in figure 3.34
// Figure 3.34 typedef struct { unsigned int gp_offset; unsigned int fp_offset; void *overflow_arg_area; void *reg_save_area; } va_list[1];
If you pass your va_list
into the first vprintf
call and the function returns the va_list
will no longer be as before the call. The second call to vfprintf
will get a "wrong/consumed va_list
" then.
Solution:
Either use va_copy
after va_start
or use va_start
2 times if your compiler doesn't support va_copy
. But remember each call to va_copy
or va_start
needs a corresponding call to va_end
.
Upvotes: 3