I'm trying to write a few wrappers for the standard sprintf function from cstdio. However, I'm having some weird behaviour and access violation crashes when running my program. I've simplified the problem and reproduced it on the code below:
#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;
}
This code produces a memory access violation when calling vsprintf in vfmt. However, when I change fmt's function signature from fmt(const std::string& format, ...) to fmt(const char* format, ...), I no longer crash, and everything works as expected. Why exactly is this happening?
Why is it that changing the type of the format parameter from const std::string& to const char* solves the issue? Or does it only appear to be solved?
args. It's callingvsprintfand checking if the result string fits the buffer. If not, it resizes the buffer and tries again until it does.vsprintfinstead ofvsnprintf, or any of its C++ replacements?#define _CRT_NO_VA_START_VALIDATIONsome people have seen this error starting to compile with VS2015, previously no problem.