VFprintf 无法正常工作

vfprintf doesn't work properly

本文关键字:工作 常工作 VFprintf      更新时间:2023-10-16

我有一个类:

FILE *logFile = fopen("out.log", "w");
class Log {
public:
static void d(const char *message, ...) __attribute__((format (printf, 1, 2)));
}

在源文件中:

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);
}

但是当我调用例如Log::d("test %d %s %f", 10, "str", 0.1);它会test 0 @WAíõ 0,000000打印到文件中时。

怎么了?

问题是您使用va_listargptr2 次。一次在vprintf中,第二次在vfprintf通话中。va_list如何与堆栈一起工作是实现定义的,请参阅此处。例如,va_list类型是在 Linux 中实现的x86_64就像在 SO 上所说的那样:

va_list类型

va_list 类型是一个数组,其中包含一个结构的单个元素,其中包含实现va_arg宏所需的信息。va_list类型的C定义如图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];

如果将va_list传递到第一个vprintf调用中,并且函数返回,则va_list将不再像调用之前一样。第二次调用vfprintf将得到"错误/消耗va_list"。

溶液:

va_start后使用va_copy,或者如果您的编译器不支持va_copy,则使用va_start2 次。但请记住,每次调用va_copyva_start都需要相应的调用va_end