Предупреждение компилятора (уровень 2) C4412
Обновлен: Ноябрь 2007
Сообщение об ошибке
"функция": подпись функции содержит тип "имяТипа"; объекты C++ небезопасно передавать между структурами чистого и смешанного или машинного кода.
'function' : function signature contains type 'type'; C++ objects are unsafe to pass between pure code and mixed or native.
Компилятор обнаружил потенциально небезопасную ситуацию, которая может привести к возникновению ошибки во время выполнения: вызов из компилянта /clr:pure функции, импортированной с помощью dllimport, а также наличие в сигнатуре функции небезопасного типа. Тип является небезопасным, если его функция-член или член данных относится к небезопасному типу или косвенно обращается к нему.
Это является небезопасным из-за разницы в соглашениях о вызовах, используемых по умолчанию для чистого и машинного кода (или смешанного — неуправляемого и управляемого). При импорте функции (с помощью dllimport) в компилянт /clr:pure следует убедиться, что объявления каждого типа в сигнатуре являются идентичными объявлениям в компилянте, который экспортирует функцию (проявляя особую осторожность в отношении соглашений о неявных вызовах).
Виртуальная функция-член зачастую может привести к непредвиденным результатам. Однако, чтобы убедиться, что результаты будут правильными, необходимо проверять и невиртуальные функции. Если пользователь уверен в правильности результатов, данное предупреждение можно игнорировать.
Дополнительные сведения о /clr:pure см. в разделе Практическое руководство. Миграция в /clr:pure.
Предупреждение C4412 по умолчанию отключено. Дополнительные сведения см. в разделах Compiler Warnings That Are Off by Default и 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
}