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?