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 なので、その場所に置くのは決して正しくない。
コードにブレークポイント使って確認して、意外なことは発見した
このexpressionの戻り値は < 0
lstrcmpA("impS", "S")
この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