Оператор удаления 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).

Сообщение об ошибке от отладчика VS

Теперь, почему мы получаем эту ошибку, когда этот конкретный оператор (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; Поведение таково: ваша программа иногда падает, иногда нет.

Другие вопросы по тегам