std::string 和 stdarg.h
我编写了一个函数,它尝试通过返回 std::string 而不是写入用户提供的 char* 来执行自动分配 sprintf。 (拜托,没有推荐 iostreams 或 Boost.Format 或朋友的答案 - 我知道它们存在,我确实在其他上下文中使用它们,但对于这种特殊情况有一个要求。)
std::string FormatString(const std::string& format, va_list argList)
{
char smallBuffer[500], *text = smallBuffer;
int length = _countof(smallBuffer);
// MSVC is not C99 conformant, so its vsnprintf returns -1
// on insufficient buffer space
int outputSize = _vsnprintf(text, length, format.c_str(), argList);
while (outputSize < 0 && errno == ERANGE && length > 0)
{
length <<= 1;
if (text != smallBuffer) { delete[] text; }
text = new char[length];
outputSize = _vsnprintf(text, length, format.c_str(), argList);
}
if (outputSize < 0)
{
throw std::runtime_error("Failed to format string.");
}
std::string ret(text);
if (text != smallBuffer)
{
delete[] text;
}
return ret;
}
std::string FormatString(const std::string& format, ...)
{
va_list argList;
va_start(argList, format);
std::string result;
try
{
result = FormatString(format, argList);
}
catch(...)
{
va_end(argList);
throw;
}
va_end(argList);
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int foo = 1234;
std::string bar = "BlaBla";
std::cout << FormatString("%i (%s)", foo, bar.c_str()) << std::endl;
return 0;
}
(是的,我看到了管道 a 的讽刺意味C 格式的字符串到 C++ iostream。这只是测试代码。)
不幸的是,使用 VS2008,它在 printf 内部深处崩溃了,显然是因为它读取了错误的参数。 va_list
(根据调试器的说法,在 va_start
之后,它指向“真实”第一个参数之前的一个四字节空序列)。
特别值得注意的是,如果在可变参数函数中我更改了 const std::string& format 为 std::string format
(即按值传递),它可以正常工作;当然,如果我将其更改为 const char *,它也会这样做。
这是某种编译器错误,还是使用带有引用参数的 va_list 不合法?
I have written a function which tries to do an auto-allocating sprintf by returning a std::string instead of writing into a user-supplied char*
. (Please, no answers recommending iostreams or Boost.Format or friends -- I know they exist, I do use them in other contexts, but there is a requirement for this particular case.)
std::string FormatString(const std::string& format, va_list argList)
{
char smallBuffer[500], *text = smallBuffer;
int length = _countof(smallBuffer);
// MSVC is not C99 conformant, so its vsnprintf returns -1
// on insufficient buffer space
int outputSize = _vsnprintf(text, length, format.c_str(), argList);
while (outputSize < 0 && errno == ERANGE && length > 0)
{
length <<= 1;
if (text != smallBuffer) { delete[] text; }
text = new char[length];
outputSize = _vsnprintf(text, length, format.c_str(), argList);
}
if (outputSize < 0)
{
throw std::runtime_error("Failed to format string.");
}
std::string ret(text);
if (text != smallBuffer)
{
delete[] text;
}
return ret;
}
std::string FormatString(const std::string& format, ...)
{
va_list argList;
va_start(argList, format);
std::string result;
try
{
result = FormatString(format, argList);
}
catch(...)
{
va_end(argList);
throw;
}
va_end(argList);
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int foo = 1234;
std::string bar = "BlaBla";
std::cout << FormatString("%i (%s)", foo, bar.c_str()) << std::endl;
return 0;
}
(And yes, I see the irony of piping a C-formatted string to a C++ iostream. This is just test code.)
Unfortunately, using VS2008, it's crashing deep within the bowels of the printf internals, apparently because it's reading the wrong arguments out of the va_list
(according to the debugger, after the va_start
it's pointing at a four-byte null sequence immediately prior to the "real" first parameter).
Of particular note is that if in the variadic function I change the const std::string& format
to just std::string format
(ie. pass by value), it works properly; it also does so if I change it to a const char *
, of course.
Is this some sort of compiler bug, or is it not legal to use a va_list with reference parameters?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为如果你想通过推荐信你就运气不好了。以下是 C++2011 标准对 18.10 [support.runtime] 第 3 段中的主题的说明:
I think you are out of luck if you want to pass a reference. Here is what the C++2011 standard has to say about the subject in 18.10 [support.runtime] paragraph 3: