sprintf
からの標準関数のラッパーをいくつか作成しようとしていcstdio
ます。ただし、プログラムを実行すると、奇妙な動作が発生し、アクセス違反がクラッシュします。問題を単純化し、以下のコードで再現しました。
#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;
}
このコードは、 を呼び出すときにメモリ アクセス違反を引き起こしvsprintf
ますvfmt
。ただし、fmt
の関数シグネチャを からfmt(const std::string& format, ...)
に変更するfmt(const char* format, ...)
と、クラッシュしなくなり、すべてが期待どおりに機能します。なぜこれが起こっているのですか?
format
パラメータのタイプをからconst std::string&
に変更const char*
すると問題が解決するのはなぜですか? それとも解決したように見えるだけですか?