lstrcmpA ≠ strcmp

多分中二病の発症とか何とか、とりあえず理由は忘れた。
何年前に私は書いたインポートライブラリ作成ツールに、文字列の比較はC言語のstrcmpの代わりにWindows APIのlstrcmpAを使った。
VC用の.libファイルに、二番目のメンバーはこのライブラリーに全部使われるシンボルの集合だ。シンボルに要求は「lexical」順に並べる。*1
それは簡単なアルゴリズムだね:ソート。
ソートの時文字列の比較は必要だ。あの時は私はstrcmpの代わりにlstrcmpAを使った。多分「Windowsから提供のAPIを使ってみたい」だろう、もうわかんない><

あのツールは今夜使った時、使えない.libを作成した。具体的に、linker.exeは時々「LNK2001:外部シンボルは未解決です」とリンクエラーになった。「一部のシンボル」で、「全部」じゃなかった。例えばimpSは使えるがSは使えない。
それは本当におかしい。.libファイルをバイナリ編集ツールで検索したら、シンボルテーブルに確かにそのシンボルがある。

dumpbinツール使って、私のツールで作成した.libファイルの詳しい情報を調べて、不具合の所は発見した

確かに大文字の「S」は小文字の「i」より値が小さいはず?しかもNULL_THUNK_DATAの最初の文字は 0x7f なので、その場所に置くのは決して正しくない。

コードにブレークポイント使って確認して、意外なことは発見した


lstrcmpA("impS", "S")
このexpressionの戻り値は < 0

このlstrcmpAをstrcmpにしていろいろ試したら、今まで問題なし

MSDNでlstrcmpの説明を調べて、

The function calls CompareString, using the current thread locale, and subtracts 2 from the result, to maintain the C run-time conventions for comparing strings. *2

確かに普通のstrcmpではない。

でもこのコードの書いたとき、どうしてlstrcmpAを使ってたのだろう・・・

インポートライブラリ作成のツールのソースコードは、整理終わったらgithubにupするつもり。ちょっと汚いけど

*1: The second linker member includes symbol names in lexical order, which enables faster searching by name. http://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/pecoff.doc

*2:http://msdn.microsoft.com/EN-US/library/ms647488(v=VS.85,d=hv.2).aspx