リンカー ツールの警告 LNK4049
'filename.obj' で定義されているシンボル 'symbol' がインポートされます
同一イメージ内のオブジェクト ファイル filename.obj でシンボルが定義されているにもかかわらず、__declspec(dllimport) が symbol に指定されました。 この警告を解決するには、 __declspec(dllimport)
修飾子を削除します。
解説
この警告は、あるオブジェクト ファイルでシンボルを定義し、別のオブジェクト ファイルで __declspec(dllimport)
宣言修飾子を使用してそれを参照したときにリンカーによって生成されます。
警告 LNK4049 は、リンカー ツールの警告 LNK4217 より一般的なバージョンです。 リンカーは、インポートされたシンボルがどの関数またはオブジェクト ファイルを参照しているかを判断できない場合、警告 LNK4049 を生成します。
LNK4217 ではなく LNK4049 が生成される一般的なケースは次のとおりです。
/INCREMENTAL オプションを使用する場合。
/LTCG オプションを使用する場合。
LNK4049 を解決するには、次のいずれかの手順を試行してください:
LNK4049 をトリガーしたシンボルの前方宣言から
__declspec(dllimport)
修飾子を削除します。 DUMPBIN ユーティリティを使用して、バイナリ イメージ内のシンボルを検索できます。 DUMPBIN /SYMBOLS スイッチには、イメージの COFF シンボル テーブルが表示されます。 DUMPBIN ユーティリティの詳細は、DUMPBIN リファレンスを参照してください。増分リンクとプログラム全体の最適化を一時的に無効にします。 再コンパイルすると、アプリケーションによって警告 LNK4217 が生成されます。これには、インポートされたシンボルを参照する関数の名前が含まれます。 インポートしたシンボルから
__declspec(dllimport)
宣言修飾子を削除し、必要に応じて増分リンクまたはプログラム全体の最適化を再度有効にします。
最終的に生成されたコードは正しく動作しますが、インポートされた関数を呼び出すために生成されるコードは、関数を直接呼び出すよりも効率が悪くなります。 この警告は、/clr オプションを使用してコンパイルした場合には表示されません。
データのインポートとエクスポート宣言の詳細は、dllexport、dllimport を参照してください。
例
次の 2 つのモジュールをリンクすると、LNK4049 が生成されます。 最初のモジュールは、エクスポートされた関数を 1 つ含むオブジェクト ファイルを生成します。
// LNK4049a.cpp
// compile with: /c
__declspec(dllexport) int func()
{
return 3;
}
2 番目のモジュールは、1 番目のモジュールでエクスポートされた関数への前方宣言と、main
関数内でのこの関数への呼び出しを含むオブジェクト ファイルを生成します。 このモジュールを最初のモジュールとリンクすると、LNK4049 が生成されます。 宣言から __declspec(dllimport)
修飾子を削除して、警告を解決します。
// LNK4049b.cpp
// compile with: /link /WX /LTCG LNK4049a.obj
// LNK4049 expected
__declspec(dllimport) int func();
// try the following line instead
// int func();
int main()
{
return func();
}