__invalid_parameter_noinfoの解決法は?

VisualC++(VisualStudio2005 or VisualStudio2008の)で作られたプログラムではデバッグビルドとリリースビルドのライブラリを混合してリンクを行おうとすると

error LNK2001: 外部シンボル “__invalid_parameter_noinfo” は未解決です。

のように言われることが多々あります。

これの理由は単純で、リリースビルド(というかリリース用のSTLライブラリ)を連結して作られたライブラリにはこの__invalid_parameter_noinfoというルーチンが使用されています。

で、これはデバッグビルド(=デバッグ用のSTLライブラリ)には含まれていないのでこんな現象になります。

これを何とかしないとデバッグ状態でプログラムを実行できないというちょっと困った現象になることがあります。

というわけで解決法ですが・・・・

作成されるプログラム内で使っているライブラリルーチンにSTLが含まれるなら正しいライブラリを選択してライブラリを作り直さなければならい

この条件に該当する例としては

class CHoge{
public:
	int HogeA(void)
	{
		//ここではSTLを使用する(例ではvector)
		std::vector vec;
		・・・
		return 0;
	}
	int HogeB(void)
	{
		//ここではSTLは使用されない
		・・・
		return 1;
	}
};

の状態でCHogeのHogeAを呼び出さなければならない場合です。この場合にはあきらめてCHogeを含むライブラリを作成する時に

コンパイルオプションとして/MTdなどを与えて再度作り直す必要があります。ライブラリをこのような形で使用するならビルドの構成を別に用意しておいた方がいいです。

(最適化+デバッグライブラリの連結を指定した構成のようなもの)

ライブラリで使用するルーチンにSTLが含まれていない場合

上記の例で言うなら、CHogeのHogeBを使用するけれどもHogeAは使用しない、という場合です。

この場合でもデバッグビルドでは(不要関数呼び出しの除外がないときには)処理が連結されますのでSTLを使っていると勘違いされます。

その場合に関してだけは避ける方法があります。

ライブラリのビルドでコンパイルオプションに/D_SECURE_SCL=0を設定する

すると__invalid_parameter_noinfoの呼び出しが無効になる・・様な感じです。興味があるなら調べてみてください。

リンクする側のプログラムのコード内に__invalid_parameter_noinfoのスタブルーチンを記述する

具体的には

#if defined(_MSC_VER) && defined(_DEBUG)
extern "C" _CRTIMP void __cdecl _invalid_parameter_noinfo(void) {  }
#endif

を記述すると処理自体は存在することになるのでリンクエラーは回避できます。

が、実行時にSTLを呼び出すルーチンを通過する時にエラーは起こる

前述したとおり、対象のライブラリで「STLが呼び出されないこと」が条件です。

呼び出されるとそのタイミングで予期しないエラー(変なメモリアクセスエラーなど)が発生しますのでデバッグ中だと別の要素と勘違いする羽目になります。

もちろん緊急回避的な要素が大きいです。または他人が作ったライブラリを使っていて自分でライブラリを作ることができない時に

無理矢理プログラムを実行させるために使う方法です。リリース時にはこんなことはほとんど起こらないはずなので気にするのはデバッグ時だけですが・・・。

コメントを残す

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

この記事のトラックバック用URL