WindowsVista / Windows7 に含まれる mfc42u.dll の不具合について

(2010-02-07)
DYNA v2.20 以降では 開発環境の変更により mfc42u.dll を参照しなくなりました。v2.20以降に更新してください。
以下は古いバージョンでのお話です。

Windows Vista/Windows 7 に含まれる mfc42u.dll に不具合がある件について、その解説を少し。理屈とかどうでもいい人は読み飛ばしてください。
mfc42u.dll は、VisualC++ 6.0 で開発されたMFCアプリケーションで使用されるDLLです。Windows Vista 以降に同梱されているバージョンのDLLでは、MFCに用意されているハッシュ関数の1つ、ANSI文字列のハッシュ値を求める関数 HashKey<LPCSTR> が正常に機能しません。
以下、検証コードです。
const int BufferLength = 16;
char buffer[ BufferLength ];
srand( GetTickCount() );
for( int i=0; i<8; i++ )
{
    for( int j=0; j<BufferLength; j++ ) buffer[j] = rand();
    strcpy( buffer, "TestString" );
    printf( "Hash of '%s' is %08X.\n", buffer, HashKey<LPCSTR>( buffer ) );
}
この検証コードでは、バッファを乱数で埋め尽くしてから文字列を書き込んでそのハッシュを求める、という動作を8回繰り返します。書き込む文字列("TestString")は毎回同じなのだから、文字列より後ろの領域がどんな値でも、毎回同じハッシュ値になるはずです。実際にXP環境では同じ値を表示します。
しかし、VistaやWin7ではなんと毎回違う値を表示します。文字列の終端を超えた位置のデータまで参照してハッシュ値を計算してしまっていると考えられます。
試しに文字列の終端を示す 0 (null文字) を1つ多く付け加えると不具合は発生しなくなるので、終端条件を間違えているか、もしくはUnicode文字列と同じ処理をしているものと思われます。

だいなで書庫を操作するために利用してるライブラリ(CommonArchiverLibrary)ではファイル名などはすべて シフトJIS(プログラム上の扱いはANSI文字) を使う必要があり、Unicode版においてもこれは変わりません。そして、書庫を開いた時に書庫内フォルダの名前を CMap というMFCの連想配列(メモリ上の辞書)に格納して管理していたのですが、CMapの内部で上記の関数(HashKey<LPCSTR>)が使われているため、この不具合が発覚しました。

なお、この不具合が起こるのは Unicode版(mfc42u.dll)だけで、ANSI版(mfc42.dll)では発生しません。


対処方法

v2.20 以降では 開発環境の変更により mfc42u.dll を参照しなくなりました。v2.20以降に更新してください。以上。

Unicode版だいなの実行ファイル(DYNA.exe)と同じ場所に、問題の起きない mfc42u.dll を置いてください。以上。

……で、その「問題の起きない mfc42u.dll」ってのはどこから手に入れればいいの? ってな話ですが、Microsoftが定める再配布条件に「開発したアプリケーションと共に」っていうのがあって、DLL単体での再配布は認められていません。Microsoft自身が配ってくれてもよさそうなんですが、開発者向けのサイズの大きなものだったり、セキュリティパッチに同梱されているものだったりで、単体で配布している様子はありません。

なので、問題の起きるDLLかどうかを判定するツールを用意してみました。このツールにmfc42u.dllを同梱しておきます(下記のVS6SP6に付属のもの)。
このツールのexeだけを抜き出して実行すると、不具合が発生する環境かどうかを簡単に確認できます。

少し古いけど公式な mfc42u.dll の入手の仕方について。Visual Studio 6.0 Service Pack 6 の分割ダウンロードVs6sp6S1.exe (約2.76MB)に含まれる vcredist.exe を展開(自己解凍)することで入手可能。
これより新しい(&バグの無い)mfc42u.dllの公式な入手先を知っていたら誰か教えてください。


掲示板

戻る