仕事で使ったほうがよいのかどうか判定するため、Hamanaの環境をVS2003からVS2005に移してみた。
コンパイルはほとんど一発で通ったが、ものすごい数の警告がでる。原因は
strcpy() などのセキュアでない古い関数を使っているためで、親切に 「
strcpy_s()使ったほうがいいじゃない?」と警告をだしてくれるからであった。
もちろん pragmaで表示しないようにもできるが、これには素直に従ったほうが良さそうなので、大部分はセキュアなバージョンに置き換えた。
で、VS2005移行時に一番危険だと思ったのは以下のコードがコンパイルはできるが、実行するとファイルのオープンに失敗してしまい、正しく動かなくなることだ。
int main() {
std::ofstream ofs("日本語.txt", ios_base::out | ios_base::trunc);
if (ofs.is_open()) {
ofs << "OK";
}
return 0;
}
日本語のファイル名を
ofstream::open()関数に渡すとアウトらしい。英語のファイル名だと問題ないのでかなり危険だ。
デバッガで追ってみると
open()関数内部で マルチバイト文字列からワイド文字列への変換を行っているのだが、そこが正しく変換してくれないことが原因だった。
どうやら
ofstream::open()関数の実装が変わり、VS2003ではマルチバイト文字列のまま扱っていたのが、VS2005ではワイド文字に変換してから扱うようになったため、変換がうまく動くようにロケールを設定してあげないといけないようだ。
てことで、
open()を呼び出す前に
setlocale(LC_ALL, "Japanese"); を呼び出してロケールを日本語に設定することでうまく動作するようになった。多言語対応のアプリケーションの場合は以下のようにシステム標準のロケールを設定するといいと思われる。
int main() {
setlocale(LC_ALL, "");
std::ofstream ofs("日本語.txt", ios_base::out | ios_base::trunc);
if (ofs.is_open()) {
ofs << "OK";
}
return 0;
}
もう1点動かしてみて初めて発覚した問題は time_t のサイズが32bit → 64bitに増えていることだ。
susieプラグインのインターフェースに time_t型の変数を含む構造体があるのだが、見事にここでコケていた。
time_t型をシリアライズしたり、他DLLに渡している場合は注意が必要だ。