Dela via


Kompilatorvarning (nivå 2, av) C4412

'funktion': funktionssignaturen innehåller typen 'typ'; C++-objekt är osäkra att skicka mellan ren kod och blandad eller inbyggd kod.

Anmärkningar

Kompilatoralternativet /clr:pure är inaktuellt i Visual Studio 2015 och stöds inte från och med Visual Studio 2017. Om du har kod som måste vara CLR ren rekommenderar vi att du porterar den till C#.

Kompilatorn identifierade en potentiellt osäker situation som kan leda till ett körningsfel: ett anrop görs från kod som kompileras med /clr:pure till en funktion som importeras via dllimportoch funktionssignaturen innehåller en osäker typ. En typ är osäker om den innehåller en medlemsfunktion eller har en datamedlem som är en osäker typ eller indirekt till en osäker typ.

Det här mönstret är osäkert på grund av skillnaden i standardanropskonventionerna mellan ren och intern kod (eller blandad intern och hanterad). När du importerar en funktion via dllimport till kod som kompilerats med /clr:purekontrollerar du att deklarationerna för varje typ i signaturen är identiska med signaturen i kompileringen och att exporterar funktionen (särskilt noga med skillnader i implicita anropskonventioner).

En virtuell medlemsfunktion är särskilt benägen att ge oväntade resultat. Men även en icke-virtuell funktion bör testas för att säkerställa att du får rätt resultat. Den här varningen kan ignoreras när du ser till att resultatet är korrekt.

C4412 är inaktiverad som standard. Mer information finns i Kompilatorvarningar som är av som standard och dllexport, dllimport.

Lös den här varningen genom att ta bort alla funktioner från typen.

Examples

I följande exempel genereras 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
}

Följande exempel är en rubrikfil som deklarerar två typer. Typen Unsafe är osäker eftersom den har en medlemsfunktion:

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

Det här exemplet exporterar funktioner med de typer som definierats i huvudfilen:

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

Standardanropskonventionen i en /clr:pure kompilering skiljer sig från en intern kompilering. När C4412.h ingår, blir standardvärdet för Test__clrcall.

I följande exempel genereras C4412 och ett undantag genereras vid körning:

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