#c# #.net #visual-studio-2010 #c#-4.0 #interop
#c# #.net #visual-studio-2010 #c #-4.0 #взаимодействие
Вопрос:
У меня есть простой тестовый код, подобный этому —
public void GetHashCodeTest1()
{
MyComPointer target = new MyComPointer();
MyComPointerAccessor privateTarget = new MyComPointerAccessor(target);
privateTarget._pObject = new IntPtr(1);
int i = target.GetHashCode();
}
чтобы проверить это —
public override int GetHashCode()
{
if (IsEmpty)
return 0;
if (_pIUnknown == IntPtr.Zero)
{
Guid iUnknownGuid = new Guid("00000000-0000-0000-C000-000000000046");
Marshal.QueryInterface(_pObject, ref iUnknownGuid, out _pIUnknown); //<--CRASH HERE
}
return (int)_pIUnknown;
}
И он разбился при вызове Marshal.QueryInterface и вызвал ошибку FEEE —
Ошибка FatalExecutionEngineError была обнаружена
Сообщение: Среда выполнения обнаружила неустранимую ошибку. Адрес ошибки был 0x5ba46832 в потоке 0x2354. Код ошибки 0xc0000005. Эта ошибка может быть ошибкой в CLR или в небезопасных или не поддающихся проверке частях пользовательского кода. Распространенные источники этой ошибки включают ошибки маршалинга пользователя для COM-interop или PInvoke, которые могут повредить стек.
Это произошло только при запуске в .NET 4.0. Код отлично работает в .NET 2.0.
Я могу исправить проблему, заменив
Marshal.QueryInterface(_pObject, ref iUnknownGuid, out _pIUnknown);
с
_pIUnknown = Marshal.GetIUnknownForObject(_pObject);
Но я понятия не имею, почему. Кто-нибудь может помочь объяснить это?
Комментарии:
1. Первым аргументом QueryInterface() должен быть указатель на COM-интерфейс. IntPtr(1) не является допустимым указателем. Это никогда не сработает, ни в версии 2.0.
2. Это тестовый код, поэтому IntPtr (1) передается для QI. Я согласен, это может не сработать в реальном коде продукта, но этот тестовый код прошел в .NET 2.0 без сбоев QTAgent32.exe. Тот же код произошел сбой в версии 4.0.
3. Вы хотите сказать, что VS2010 «исправил» это, чтобы оно больше не работало?
4. Что ж, в системе взаимодействия COM в .NET 4, безусловно, произошли изменения. Среда CLR теперь поддерживает несколько экземпляров самой себя в процессе, в частности, для решения проблемы с внедрением COM-версии. Да, не стесняйтесь интерпретировать это как «исправление».