C++ 标准参数:多次调用va_start
C++ Standard Args : multiple calls to va_start
我注意到在两个函数中连续调用时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 %dn", x).c_str());
error("Test %dn", x);
}
生产
Test 10
Test -1078340156
似乎在使用error
函数时,参数已损坏。
将va_list
传递给另一个函数的正确方法是什么?
您可以将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++中,您应该使用可变参数模板来执行此操作,因为这些模板可以正确转发,完全类型安全,并且(如果正确实现它)不会有缓冲区溢出的风险。
希望这有帮助!
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用