共用方式為


編譯器警告 (層級 2,關閉) C4412

'function':函數簽章包含類型'type';C++ 物件在純程式碼與混合或原生程式碼之間傳遞是不安全的。

備註

編譯器選項在 /clr:pure Visual Studio 2015 中已被取代,而且從 Visual Studio 2017 開始不支援。 如果您有需要 CLR 純程式碼的程式碼,建議您將其移植至 C#。

編譯器偵測到可能導致執行階段錯誤的潛在不安全狀況:正在從編譯的 /clr:pure 程式碼呼叫透過 匯入的 dllimport函數,且函數簽章包含不安全的類型。 如果類型包含成員函式,或具有不安全型別的數據成員或不安全型別的間接性,則類型是不安全的。

此模式不安全,因為純程式碼與原生程式碼 (或混合原生與受控) 之間的預設呼叫慣例有差異。 將函數 via dllimport 匯入 編譯的 /clr:pure程式碼時,請確保簽章中每種類型的宣告與匯出函數的編譯器中的簽章相同(特別注意隱含呼叫慣例的差異)。

虛擬成員函式特別容易產生非預期的結果。 但是,即使是非虛擬函數也應該進行測試,以確保您獲得正確的結果。 一旦您確保結果正確,就可以忽略此警告。

C4412 預設為關閉。 如需詳細資訊,請參閱 預設關閉的編譯器警告dllexportdllimport

若要解決此警告,請移除類型中的所有函式。

範例

下列範例會產生 C4412:

// 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

下列範例會產生 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
}