XREA.COM Logo XREA.COM Ad

旧雑記サルベージ

110管理人 ★:06/09/06 17:47 ID:???
2006年03月04日
■Visual C++ 2005 Express EditionでAutoHotkeyをビルドする

スクリプトが肥大化してきたら気まぐれで発生するようになった謎のエラーを何とかしたい。
エラー内容を見ると、「0x0000000f」というアドレスを参照しているらしい。
0x00000000ではないということは、構造体へのポインタがnullの時にメンバを参照しようとしているのだろう。

そんなわけで、ソースコードから問題の箇所を探そうとしたが、やたらと長大で挫折した。
デバッグ実行でエラーを発生させて問題の箇所を見つけてみることに。

どうやらVC7向けに作られているらしく、手持ちのVC6.0ではコンパイルできなかったので、無償提供されているVC2005EEを使うことに。
XPのSP2にしかインストールできないということで、サブマシンにインストールする。
DaemonToolsで配布isoイメージをマウントしてインストールを行い、AutoHotkeyのプロジェクトをインポートしてみたが、windows.hがないとか言われてビルドできない。
PlatformSDKがインストールされなかったらしい。
Visual Studio 2005 Express Editions_ Visual C++ 2005 Express Edition と Microsoft Platform SDK を一緒に使う(http://www.microsoft.com/japan/msdn/vstudio/express/visualc/usingpsdk/)というページに従ってインストールする。
合わせて50分くらいかかった。

とりあえずビルドを試みると、死ぬほど警告が表示された。
プロジェクトの設定で警告を切ると、いくつかのエラーが残った。
「for(char suffix」という宣言が利いていない問題は、言語の拡張設定で直った。
const char*をchar*に変換できないというエラーは、よく分からないので引数からconstを削除して黙らせた。
宣言の型が指定されていない部分がいくつかあったが、適当にintと書き足したら大人しくなった。

コンパイルは成功するようになったが、リンク時にリソースが重複しているとか言われてビルド完了できない。
設定で埋め込みマニフェストを無効にしたら、とりあえず回避できた。


そんなわけで、とりあえずビルドできたので、問題のあるスクリプトを実行させてデバッグしてみる。
GUIウィンドウが表示されてエラーが発生すると、実行中だった箇所や関数の呼び出し元、変数の内容などの情報が表示された。
思った通り、nullなオブジェクトの関数を呼び出している部分があった。
関数のローカル変数の情報を格納するオブジェクトのアドレスを格納する部分が、不正にnullになっているらしい。
通常は正しいアドレスが格納されていたので、どこかで上書きされてしまっているのだろう。

いつnullになってしまうのか調べるため、ブレークポイントを仕掛けてそのアドレスの変更を監視したところ、strlcpy関数で文字列のコピーを行っているときに上書きされてしまっているらしいことが分かった。
問題の箇所はscript.cppの以下の部分。
VarSizeType Script::GetFileDir(char *aBuf)
{
    char buf[MAX_PATH + 1]; // Uses +1 to append final backslash for AutoIt2 (.aut) scripts.
    char *target_buf = aBuf ? aBuf : buf;
    strlcpy(target_buf, mFileDir, MAX_PATH);    //!!!!!!!!!!!!!!!!!
aBufの指すアドレスにMAX_PATHを足すと、ちょうどnullになってしまった領域をまたいでいる。
aBufとして確保されている領域のサイズを考慮せずにMAX_PATH文字をコピーしてしまっているのが原因らしい。
呼び出し元を追跡すると、その変数の領域は64バイトしか確保されていないらしかった。

strlcpyが元の文字列の終端以降もコピーを行うのは妙な気がするが、Wikipediaの説明には指定されたサイズを超えないとしか書かれていないので、サイズ分丸ごとコピーされても文句は言えない。
と思ったら、よく見たらutil.hの中で自前で定義されていて、strncpyに丸投げされていた。
VCのstrncpyの説明にはコピー元の文字列が短かった場合は残りの部分を\0で埋めると書いてあったので、正しい動作らしい。

そんなわけで、原因はおおよそ特定できたが、改善策を考えるのが面倒なのであきらめた。
作者が適当に修正してくれることを祈る。


スクリプトの方は、適当にダミーの関数を追加したらとりあえず動くようになった。
いつ駄目になるか分からないので困る。
131KB
名前: E-mail:
ファイル:
0ch BBS 2005-10-08