編譯器警告 (層級 2) C4412
'function' : 函式簽章包含類型 'type';C++對象在純程式代碼與混合或原生之間傳遞是不安全的。
備註
Visual Studio 2015 中已淘汰 /clr:pure 編譯程序選項,Visual Studio 2017 不支援。 如果您有需要純潔的程序代碼,建議您將其移植到 C#。
編譯程式偵測到可能導致運行時間錯誤的可能不安全狀況:呼叫是從 /clr:pure 編譯和匯入至透過 dllimport 匯入的函式,而函式簽章包含不安全的類型。 如果類型包含成員函式,或具有不安全型別的數據成員或不安全型別的間接性,則類型是不安全的。
這是不安全的,因為純和原生程式代碼之間默認呼叫慣例的差異(或混合原生和管理)。 將函式匯入 /dllimport
clr:pure 編譯程式時,請確定簽章中每個型別的宣告都與編譯中的宣告相同,並導出函式(特別小心隱含呼叫慣例的差異)。
虛擬成員函式特別容易產生非預期的結果。 不過,即使是非虛擬函式也應該進行測試,以確保您取得正確的結果。 如果您確定收到正確的結果,您可以忽略此警告。
C4412 預設為關閉。 如需詳細資訊,請參閱 默認 關閉的編譯程式警告和 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
}
下列範例是宣告兩種型別的頭檔。 型 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
}