Поделиться через


Предупреждение компилятора (уровень 2) C4412

"function": сигнатура функции содержит тип "type"; Объекты C++ небезопасны для передачи между чистым кодом и смешанным или собственным кодом.

Замечания

Параметр компилятора /clr:pure не рекомендуется использовать в Visual Studio 2015 и не поддерживается в Visual Studio 2017. Если у вас есть код, который должен быть чистым, рекомендуется перенести его в C#.

Компилятор обнаружил потенциально небезопасную ситуацию, которая может привести к ошибке среды выполнения: вызов выполняется из /clr:pure compiland в функцию, импортируемую через dllimport, и подпись функции содержит небезопасный тип. Тип небезопасн, если он содержит функцию-член или имеет элемент данных, который является небезопасным типом или косвенным для небезопасного типа.

Это небезопасно из-за разницы в соглашениях о вызовах по умолчанию между чистым и машинным кодом (или смешанным собственным и управляемым). При импорте функции (через dllimport) в компилятор /clr:pure убедитесь, что объявления каждого типа в сигнатуре идентичны тем, которые экспортируют функцию (особенно внимательно относятся к различиям в неявных соглашениях о вызовах).

Функция виртуального члена особенно подвержена непредвиденным результатам. Однако даже не виртуальная функция должна быть проверена, чтобы убедиться, что вы получите правильные результаты. Если вы уверены, что вы получаете правильные результаты, вы можете игнорировать это предупреждение.

По умолчанию C4412 отключен. Дополнительные сведения см . в предупреждениях компилятора, отключенных по умолчанию и 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
}