我想从cstdio
中为标准sprintf
函数编写几个包装。但是,运行我的程序时,出现了一些奇怪的行为和访问冲突崩溃。我已经简化了问题并再现它下面的代码:C++变量参数和vsprintf
#include <string>
#include <cstdio>
#include <cstdarg>
std::string vfmt(const std::string& format, va_list args)
{
int size = format.size() * 2;
char* buffer = new char[size];
while (vsprintf(buffer, format.c_str(), args) < 0)
{
delete[] buffer;
size *= 2;
buffer = new char[size];
}
return std::string(buffer);
}
std::string fmt(const std::string& format, ...)
{
va_list args;
va_start(args, format);
std::string res = vfmt(format, args);
va_end(args);
return res;
}
int main()
{
std::string s = fmt("Hello %s!", "world");
printf(s.c_str());
return 0;
}
此代码调用vfmt
vsprintf
时产生一个内存访问冲突。但是,当我将fmt
的功能签名从fmt(const std::string& format, ...)
更改为fmt(const char* format, ...)
时,我不再崩溃,并且所有内容都按预期工作。为什么会发生这种情况?
为什么将format
参数的类型从const std::string&
更改为const char*
解决了这个问题?还是它似乎只是解决了?
@dirkgently不,那while循环不是用来解析'args'的。它调用'vsprintf'并检查结果字符串是否适合缓冲区。如果不是,则调整缓冲区大小并再次尝试,直到它结束。 – Zeenobit
是否有任何理由使用不安全的'vsprintf'而不是'vsnprintf'或其任何C++替代品? –
啊,是的,我意识到发布后大约5分钟。我的错。 :/ – dirkgently