Udostępnij za pośrednictwem


Ostrzeżenie kompilatora (poziom 2) C4412

"function": podpis funkcji zawiera typ "type"; Obiekty języka C++ są niebezpieczne do przekazywania między czystym kodem a mieszanym lub natywnym.

Uwagi

Opcja /clr:pure compiler jest przestarzała w programie Visual Studio 2015 i nieobsługiwana w programie Visual Studio 2017. Jeśli masz kod, który musi być czysty, zalecamy przenoszenie go do języka C#.

Kompilator wykrył potencjalnie niebezpieczną sytuację, która może spowodować błąd w czasie wykonywania: wywołanie jest wykonywane z pliku /clr:pure compiland do funkcji zaimportowanej za pośrednictwem dllimport, a podpis funkcji zawiera niebezpieczny typ. Typ jest niebezpieczny, jeśli zawiera funkcję składową lub zawiera element członkowski danych, który jest niebezpiecznym typem lub pośrednim typem niebezpiecznym.

Jest to niebezpieczne ze względu na różnicę w domyślnych konwencjach wywoływania między czystym i natywnym kodem (lub mieszanym natywnym i zarządzanym). Podczas importowania (za pośrednictwem dllimport) funkcji do / clr:pure compiland upewnij się, że deklaracje każdego typu w podpisie są identyczne z tymi w compiland, które eksportują funkcję (szczególnie uważając na różnice w niejawnych konwencjach wywoływania).

Funkcja wirtualnego elementu członkowskiego jest szczególnie podatna na nieoczekiwane wyniki. Jednak nawet funkcja niewirtualna powinna być testowana, aby upewnić się, że uzyskasz poprawne wyniki. Jeśli masz pewność, że otrzymujesz poprawne wyniki, możesz zignorować to ostrzeżenie.

C4412 jest domyślnie wyłączony. Aby uzyskać więcej informacji, zobacz Ostrzeżenia kompilatora, które są domyślnie wyłączone i dllexport, dllimport .

Aby rozwiązać ten problem, usuń wszystkie funkcje z typu .

Przykłady

Poniższy przykład generuje 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
}

Poniższy przykład to plik nagłówkowy, który deklaruje dwa typy. Typ Unsafe jest niebezpieczny, ponieważ ma funkcję składową.

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

Ten przykład eksportuje funkcje z typami zdefiniowanymi w pliku nagłówkowym.

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

Domyślna konwencja wywoływania w kompilacji /clr:pure różni się od kompilacji natywnej. Po dołączeniu Test pliku C4412.h wartość domyślna to __clrcall. Jeśli skompilujesz i uruchomisz ten program (nie używaj /c), program zgłosi wyjątek.

Poniższy przykład generuje 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
}