在两个函数中连续调用时,我注意到va_start
有些问题。一个基本的例子如下:
std::string format(std::string fmt, ...)
{
char buf[2000];
va_list aq;
va_start(aq, fmt);
vsprintf(buf, fmt.c_str(), aq);
va_end(aq);
return std::string(buf);
}
void error(std::string fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf("%s", format(fmt, ap).c_str());
va_end(ap);
exit(1);
}
int main()
{
int x = 10;
printf("%s", format("Test %d\n", x).c_str());
error("Test %d\n", x);
}
产生
Test 10
Test -1078340156
似乎在使用error
函数时,参数已损坏。
将va_list
传递给另一个函数的正确方法是什么?
答案 0 :(得分:11)
您可以明确地将va_list
作为参数传递。将va_list
传递给采用多个参数的函数不会“解包”这些参数。相反,它只是用两个参数调用函数,第二个参数是va_list
。你从函数中获取垃圾的原因是它试图将va_list
解释为printf
的一个参数,导致未定义的行为。
这就是vsprintf
这样的函数的原因 - 这样,printf
或sprintf
等函数可以在内部调用辅助函数来进行格式化,给定va_list
争论。
例如:
std::string vformat(std::string fmt, va_list args) {
char buf[2000];
vsprintf(buf, fmt.c_str(), args);
return std::string(buf);
}
void error(std::string fmt, ...) {
va_list ap;
va_start(ap, fmt);
printf("%s", vformat(fmt, ap).c_str());
va_end(ap);
exit(1);
}
尽管如此,在C ++中你应该使用可变参数模板来执行此操作,因为它们可以正确转发,完全类型安全,并且(如果正确实现)不会冒缓冲区溢出的风险。
希望这有帮助!