コンパイラの警告 (レベル 2) C4412
更新 : 2007 年 11 月
エラー メッセージ
'関数' : 関数のシグネチャが型 '型' を含んでいます。C++ オブジェクトを、純粋なコードと混合またはネイティブ コードとの間で渡すことは安全ではありません。
ランタイム エラーを発生させる可能性がある、安全ではない状況をコンパイラが検出しました。/clr:pure コンパイル単位から、dllimport 経由でインポートされた関数に対する呼び出しを実行中ですが、その関数シグネチャに安全ではない型が含まれています。型がメンバ関数を含んでいるか、安全ではない型のデータ メンバまたは安全ではない型への間接参照を含んでいる場合、型は安全ではありません。
純粋なコードとネイティブ コード (またはネイティブ コードとマネージ コードの混合) では既定の呼び出し規約に違いがあるので、これは安全ではありません。関数を (dllimport 経由で) /clr:pure コンパイル単位にインポートする場合は、シグネチャでの各型の宣言が、関数をエクスポートするコンパイル単位内の宣言と同じであることを確認します (暗黙の呼び出し規約での違いには特に注意してください)。
特に仮想メンバ関数では、予期しない結果になる傾向があります。しかし、非仮想関数であっても、テストを実行して正しい結果が得られることを確認する必要があります。正しい結果が得られることを確認している場合は、この警告を無視できます。
/clr:pure の詳細については、「方法 : /clr:pure に移行する」を参照してください。
既定では、C4412 はオフに設定されています。詳細については、Compiler Warnings That Are Off by Default および「dllexport, dllimport」を参照してください。
この警告を解決するには、型からすべての関数を削除します。
使用例
次の例では C4412 エラーが生成されます。
// C4412.cpp
// compile with: /c /W2 /clr:pure
#pragma warning (default : 4412)
struct Unsafe {
virtual void __cdecl Test();
};
struct Safe {
int i;
};
__declspec(dllimport) Unsafe * __cdecl func();
__declspec(dllimport) Safe * __cdecl func2();
int main() {
Unsafe *pUnsafe = func(); // C4412
// pUnsafe->Test();
Safe *pSafe = func2(); // OK
}
次のコード例は、2 つの型を宣言するヘッダー ファイルです。Unsafe 型には、メンバ関数があるので安全ではありません。
// C4412.h
struct Unsafe {
// will be __clrcall if #included in pure compilation
// defaults to __cdecl in native or mixed mode compilation
virtual void Test(int * pi);
// try the following line instead
// virtual void __cdecl Test(int * pi);
};
struct Safe {
int i;
};
次の例は、ヘッダー ファイルで定義されている型で関数をエクスポートします。
// C4412_2.cpp
// compile with: /LD
#include "C4412.h"
void Unsafe::Test(int * pi) {
*pi++;
}
__declspec(dllexport) Unsafe * __cdecl func() { return new Unsafe; }
__declspec(dllexport) Safe * __cdecl func2() { return new Safe; }
/clr:pure コンパイルでの既定の呼び出し規約は、ネイティブ コンパイルの規約とは異なります。C4412.h がインクルードされている場合、Test の既定値は __clrcall になります。このプログラムを (/c を使用しないで) コンパイルして実行する場合、プログラムは例外をスローします。
次の例では C4412 エラーが生成されます。
// C4412_3.cpp
// compile with: /W2 /clr:pure /c /link C4412_2.lib
#pragma warning (default : 4412)
#include "C4412.h"
__declspec(dllimport) Unsafe * __cdecl func();
__declspec(dllimport) Safe * __cdecl func2();
int main() {
int n = 7;
Unsafe *pUnsafe = func(); // C4412
pUnsafe->Test(&n);
Safe *pSafe = func2(); // OK
}