Avviso del compilatore (livello 2) C4412
'funzione': la firma della funzione contiene il tipo 'tipo'; non è sicuro passare oggetti di C++ tra codice pure e codice misto o nativo.
Il compilatore ha rilevato una situazione potenzialmente pericolosa che potrebbe provocare un errore di runtime. È in corso l'esecuzione di una chiamata da un modulo /clr:pure a una funzione importata tramite dllimport, ma la firma della funzione contiene un tipo unsafe. Un tipo viene considerato unsafe se contiene una funzione membro o se dispone di un membro dati corrispondente a un tipo unsafe o a un riferimento indiretto a un tipo unsafe.
Questa situazione è pericolosa in quanto le convenzioni di chiamata predefinite del codice pure differiscono da quelle del codice nativo o del codice misto nativo e gestito. Durante l'importazione di una funzione tramite dllimport in un modulo /clr:pure, assicurarsi che le dichiarazioni di ciascun tipo presente nella firma siano identiche a quelle del modulo che esporta la funzione, prestando particolare attenzione alle differenze nelle convenzioni di chiamata implicite.
Le funzioni membro virtuali sono particolarmente soggette a risultati imprevisti. Tuttavia, per garantire la correttezza dei risultati, è opportuno testare anche le funzioni non virtuali. Se i risultati sono corretti, è possibile ignorare questo avviso.
Per ulteriori informazioni su /clr:pure, vedere Procedura: migrare a /clr:pure (C++/CLI).
Per impostazione predefinita, l'avviso C4412 non è attivo. Per ulteriori informazioni, vedere Compiler Warnings That Are Off by Default e dllexport, dllimport.
Per risolvere il problema, rimuovere tutte le funzioni dal tipo.
Esempio
Nell'esempio seguente viene generato l'errore 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
}
Nell'esempio riportato di seguito viene illustrato un file di intestazione che dichiara due tipi. Il tipo Unsafe è unsafe perché contiene una funzione membro.
// 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;
};
In questo esempio vengono esportate le funzioni con i tipi definiti nel file di intestazione.
// 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; }
La convenzione di chiamata predefinita in una compilazione /clr:pure differisce da quella di una compilazione nativa. Quando C4412.h è incluso, Test viene impostato sul valore predefinito __clrcall. Se questo programma viene compilato ed eseguito, senza utilizzare /c, verrà generata un'eccezione.
Nell'esempio seguente viene generato l'errore 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
}