В неповрежденном проекте C ++ внешняя (*) управляемая DLL используется через COM Callable Wrapper (CCW) (Зарегистрировано в RegAsm). Но есть утечка памяти: управляемая память никогда не очищалась.
Предыстория: проект C ++ — это старая 32-битная программа. Он загружает несколько библиотек DLL, некоторые из них являются управляемыми библиотеками (написанными на C #).
В минимальном примере .Net DLL работает нормально. Может быть, GC запутался с использованием управляемого кода различными способами?
Как заставить сборщик мусора против часовой стрелки?
Следующий код в существующем Wrapper не работает:
__declspec(dllexport) void ExecuteCcwGcWrapper(void* ComObject)
{
IntPtr ptr(ComObject);
Object^ obj = System::Runtime::InteropServices::Marshal::GetObjectForIUnknown(ptr);
try {
System::Runtime::InteropServices::Marshal::FinalReleaseComObject(obj);
}
catch (ArgumentException^ e) {
System::Diagnostics::Debug::WriteLine(e->Message);
}
catch (ArgumentNullException^ e) {
System::Diagnostics::Debug::WriteLine(e->Message);
}
catch (Exception^ e) {
System::Diagnostics::Debug::WriteLine(e->Message);
}
}
ArgumentException в «FinalReleaseComObject» -> Нет COM-объекта. В отладчике объект «obj» выглядит нормально. Структура, данные, все ок.
Следующий код будет работать, но не будет иметь никакого эффекта:
__declspec(dllexport) void ExecuteCcwGcWrapper(void* ComObject)
{
IntPtr ptr(ComObject);
while (System::Runtime::InteropServices::Marshal::Release(ptr) > 0);
//System::GC::AddMemoryPressure(0x7FFFFFFF);
System::GC::Collect();
//System::GC::WaitForFullGCComplete();
System::GC::WaitForPendingFinalizers();
}
(* У меня нет доступа к источникам)
Как обсуждалось на немецком форуме CCW GC не работает:
System::GC::Collect(System::GC::MaxGeneration, System::GCCollectionMode::Forced, true);
System::GC::WaitForPendingFinalizers();
System::GC::Collect(System::GC::MaxGeneration, System::GCCollectionMode::Forced, true);
сделает свое дело.
Грязный раствор: GC :: GetTotalMemory.
Других решений пока нет …