win7(64bit)の悲劇 - どこから湧くのよこの警告 -
多少間が空いたけれども
今回はWin7というよりは、VC2008以降のお話。
普通にC標準関数を使っていると、こんな警告がわんさか出てくるかと思うんですが…
(改行は体裁の関係で追加したものです。)
1>...\windows_main.cpp(147) : warning C4996:
'fopen': This function or variable may be unsafe.
Consider using fopen_s instead.
To disable deprecation,
use _CRT_SECURE_NO_WARNINGS.
See online help for details.
1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\stdio.h(237)
: 'fopen' の宣言を確認してください。
fopen()のみならず、strcpy()や_itoa()でも出ます。
特に前回の私同様、移行組の場合はそれはもうわんさか出ます…(苦笑)
まぁ、警告文をよく読んでみると、
「fopen():この関数(変数は)安全ではないかもしれないので、fopen_s()を使ってね♪」
といった感じのことが書いてある。
じゃぁ、「fopen→fopen_sで置換かければいいんじゃね?」…とか思ってると、
これが通用しない。
何でかというと…、
・fopen() - MSDN
・fopen_s() - MSDN
…オワカリイタダケタダロウカ?(謎)
早い話、
引数が違う。
どうも、「エラーはWINの標準エラーの方に出すから、そっちで判断しろやゴルァ!」ということらしい。
んまぁ、正直な所、あくまでも「警告」なので、
ビルドは通るし、挙動的にも問題ない。*1
ただ、結構な量の警告が出るので、気持ち悪いというのもあるが、
何より、本物の警告/エラーを見逃す恐れがある。
まぁ、なので、警告に対処しようという話。
(ここから本題)
まぁ早い話、defineでいい。
ただし、冒頭のfopen()がdefineでは対応できないので、要別途対応。
で、↓が具体例。
・cast_vc.h
/*===================================== VC2008対応用標準関数変換マクロ =====================================*/ #ifndef __CAST_VC__ #define __CAST_VC__ // VC2008対応用 #define fopen(file,type) Fopen(const_cast<char*>(file),const_cast<char*>(type)) #define _itoa(num,buf,rate) _itoa_s(num,buf,strlen(buf),rate) #define strcpy(dst,src) strcpy_s(dst,strlen(src)+1,src) #define strcat(dst,src) strcat_s(dst,strlen(src)+strlen(dst)+1,src) #define strtok(src,div) STRtoken(src,div) FILE *Fopen( char *file, char *type ); char *STRtoken( char *src, const char *div ); #endif // < __CAST_VC__
・cast_vc.cpp
#include <stdio.h> #include <string.h> // strtok_s()用 #include "cast_vc.h" // fopen()→fopen_s()変換用 static FILE *g_fp; /*===================================== fopen()→fopen_s()変換用関数 =====================================*/ FILE *Fopen( char *file, char *type ) { fopen_s( &g_fp, file, type ); return g_fp; } // strtok()→strtok_s()変換用 static char *g_token; /*===================================== strtok()→strtok_s()変換用関数 =====================================*/ char *STRtoken( char *src, const char *div ) { return strtok_s( src, div, &g_token ); }
こんな感じの.h、.cppを用意して、
ソースの頭のあたりで
#include "cast_vc.h"
でOK。
もっといい方法もあるだろうけど、まぁ一時対処には十分でしょう。
*1:挙動的には、置き換えない(=変更を加えない)方が再現性の保障を取れるんじゃないかね…。