Недопустимая операция с указателем при освобождении TStreamAdapter - PullRequest
0 голосов
/ 13 мая 2019

Может кто-нибудь уточнить, почему я получаю «Недопустимая операция с указателем» при попытке удалить TStreamAdapter?Или ... как правильно освободить память от TStreamAdapter?Это работает, если я удаляю delete, но это вызывает утечку памяти.Даже если я использую boost :: scoped_ptr, он также завершается с той же ошибкой.

Примечание: я также пытался инициализировать TStreamAdapter значением soOwned, та же ошибка.

Код:

HRESULT LoadFromStr(TWebBrowser* WB, const UnicodeString& HTML)
{
if (!WB->Document)
    {
    WB->Navigate("about:blank");
    while (!WB->Document) { Application->ProcessMessages(); }
    }

DelphiInterface<IHTMLDocument2> diDoc = WB->Document;

if (diDoc)
    {
    boost::scoped_ptr<TMemoryStream> ms(new TMemoryStream);

        {
        boost::scoped_ptr<TStringList> sl(new TStringList);
        sl->Text = HTML;
        sl->SaveToStream(ms.get(), TEncoding::Unicode);
        ms->Position = 0;
        }

    DelphiInterface<IPersistStreamInit> diPSI;

    if (SUCCEEDED(diDoc->QueryInterface(IID_IPersistStreamInit, (void**)&diPSI)) && diPSI)
        {
        TStreamAdapter* sa = new TStreamAdapter(ms.get(), soReference);
        diPSI->Load(*sa);
        delete sa;  // <-- invalid pointer operation here???

        // UPDATED (solution) - instead of the above!!!
        // DelphiInterface<IStream> sa(*(new TStreamAdapter(ms.get(), soReference)));
        // diPSI->Load(sa);
        // DelphiInterface is automatically freed on function end


        return S_OK;
        }
    }

return E_FAIL;
}

Обновление: я нашел решение здесь - http://www.cyberforum.ru/cpp-builder/thread743255.html

Решение заключается в использовании _di_IStream sa(*(new TStreamAdapter(ms.get(), soReference))); или ... DelphiInterface<IStream> sa(*(new TStreamAdapter(ms.get(), soReference)));

Как это будет автоматическиосвободите IStream, как только он выйдет за рамки.По крайней мере, так должно быть - возможна ли здесь утечка памяти?(CodeGuard не обнаружил утечек памяти).

1 Ответ

3 голосов
/ 13 мая 2019

TStreamAdapter является потомком TInterfacedObject, который реализует семантику подсчета ссылок.Вы не должны delete это вообще, вам нужно позволить подсчету ссылок освободить объект, когда на него больше никто не ссылается.

Использование _di_IStream (что является просто псевдонимом для DelphiInterface<IStream>) это правильный способ автоматизировать это с помощью умного указателя.TComInterface<IStream> и CComPtr<IStream> тоже будут работать.

...