MSVC6.0のリンクエラー

error LNK2001: 外部シンボル "__chkesp" は未解決です

というリンクエラーが出てしまって困った。ただしDebug版のみで、Releaseビルドでは起こらない。まあ、当然か。

_chkespというのは、名前の通りespをchkする関数。要するに関数ポインタコールスタックをチェックするデバッグ支援用の関数である。実際には、自分でこの関数を呼び出すことはない。DebugビルドではVCのコンパイラが自動的に、関数の呼び出し前にespをesiに保存し、呼出し後にesiとespのコンペアを行ってから_chkesp() を呼びだすコードを吐き出す。

ここまでは知っていたんだが。ではCRTライブラリを追加してみるとどうか。

リンクオプションでlibcmtd.lib(マルチスレッドなので)を追加してみると、今度は

msvcrtd.lib : error LNK2005: _sprintf はすでにlibcmtd.lib(sprintf.obj) で定義されています

と、使っているCRTライブラリの関数が多重定義となってしまう。MFCの共有DLLとバッティングしているんだろうか。わからん。

で、結局「PRB: LNK2001: Unresolved External Symbol __chkesp」に書いてあるとおり、/GZオプションを外してコールスタックの正当性チェック自体を無効にする以外にないのかと半ば諦めかけていたのだが、少し調べていたら

VC++の小技

の「CRTをぜんぜん使わないDLL」項に_chkespを実装してしまう解決方法を発見。単純に実装すると_chkesp()内のAPI呼び出しで_chkespを再帰呼出してしまう問題があるわけですか。確かに。

結局この方は内部API呼出もインラインアセンブラで実装し、__declspec(naked)を用いてプロローグ・エピローグコードを生成しないようにすることで回避しいる。

なるほど。勉強になりました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です