Оператор удаления C++ генерирует исключение из-за повреждения кучи в процессе.net 4.5
Ранее у меня было клиентское приложение.net (консольное приложение), целевая среда которого установлена на 4.0. Код клиента выглядит так:
COMProxyCustomClass proxy = new COMProxyCustomClass();
proxy.LoadFieldServiceComponent("abc", 3);
где клиент.net использует COM-тип C++ COMProxyCustom посредством ссылки на dll взаимодействия RCW, сгенерированный путем импорта TLB из C++ com-проекта. Реализация метода LoadFieldServiceComponent выглядит следующим образом:
STDMETHODIMP CCOMProxyCustom::LoadFieldServiceComponent(BSTR fscName, int version)
{
HRESULT hr = S_OK;
ILocaleManager *localeManager = NULL;
hr = CoCreateInstance(CLSID_LocaleManager, NULL , CLSCTX_ALL , IID_ILocaleManager, (void**)&localeManager);
delete(localeManager);
localeManager = NULL;
return hr;
}
И снова здесь ILocaleManager - это тип.net, который используется в проекте C++ путем экспорта TLB из проекта.net и включения / импорта его здесь, в C++ com-проект.
#import "SomeInterop.tlb" no_namespace named_guids
До сих пор все в порядке.
Здесь возникает проблема: чтобы использовать возможности, предоставляемые.net 4.5 (System.IO.Compression), я переместил проект клиента C# в целевую версию.net 4.5 (ранее это был.net 4.0). После выполнения этой миграции я начал получать ошибку поврежденной кучи при удалении оператора (localeManager).
Теперь, почему мы получаем эту ошибку, когда этот конкретный оператор (delete) выполняется в процессе.net, который нацелен на 4.5, а почему нет на 4.0, есть ли какие-либо изменения в том, как следует освобождать память в коде C++, если приложение.net, которое загружает этот код C++ для версии 4.5 платформы? и как очистить память localeManager сейчас, если удалить нельзя использовать?
1 ответ
Вы используете COM, вы должны вызывать Release() для localeManager, а не удалять его.
if (localeManager)
localeManager->Release();
COM использует счетчик ссылок для управления жизненным циклом объекта.
Поскольку C++ удаляет ключевое слово, он должен знать тип указателя, он полагается на C++ RTTI для работы; Что касается COM, он имеет другую реализацию RTTI. COM-объект имеет разную структуру размещения, чем объект C++.
Как вы сказали, удаление работает раньше, на самом деле это не так. Удаление указателя COM приведет к повреждению кучи, однако не произойдет сбоя в строке оператора delete; Поведение таково: ваша программа иногда падает, иногда нет.