Освобождение BSTR с помощью::SysFreeString(). Больше зависит от платформы?

Я пишу COM-сервер, который имеет множество интерфейсов и методов. И большинство методов имеют BSTR как параметры и как локальные параметры, используемые для возврата. Фрагмент выглядит как

Обновление 5:

Настоящий код. Это выбирает из набора данных на основе конкретного условия БД для заполнения массива объектов.

STDMETHODIMP CApplication::GetAllAddressByName(BSTR bstrParamName, VARIANT *vAdddresses)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

//check the Database server connection

COleSafeArray saAddress;
HRESULT hr;

// Prepare the SQL Strings dan Query the DB

long lRecCount = table.GetRecordCount();

 if (lRecCount > 0)
 {
    //create one dimension safe array for putting  details
    saAddress.CreateOneDim(VT_DISPATCH,lRecCount);

    IAddress *pIAddress = NULL; 
    //retrieve details 
    for(long iRet = table.MoveFirst(),iCount=0; !iRet; iRet = table.MoveNext(),iCount++)
    {
        CComObject<CAddress> *pAddress;
        hr = CComObject<CAddress>::CreateInstance(&pAddress);
        if (SUCCEEDED(hr))
        {   
            BSTR bstrStreet = ::SysAllocString(table.m_pRecordData->Street);
            pAddress->put_StreetName(bstrStreet);

            BSTR bstrCity = ::SysAllocString(table.m_pRecordData->City);
            pAddress->put_CityName(bstrCity);
        }
        hr = pAddress->QueryInterface(IID_IAddress, (void**)&pIAddress);
        if(SUCCEEDED(hr)) 
        {
            saAddress.PutElement(&iCount,pIAddress); 
        }
    }
    *vAdddresses=saAddress.Detach(); 
}
table.Close(); 
return S_OK;
}


STDMETHODIMP CAddress::put_CityName(BSTR bstrCityName)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())
    // m_sCityName is of CComBSTR Type
    m_sCityName.Empty();//free the old string 
    m_sCityName = ::SysAllocString(bstrCityName);//create the memory for the new string
    return S_OK;
}

Проблема заключается в части освобождения памяти. Код работает очень хорошо на любых машинах с Win XP, но когда дело доходит до WIN2K8 R2 и WIN7, код падает и указывает на виновника::SysFreeString(). MSDN не подходит для решения.

Может ли кто-нибудь помочь в поиске правильного решения?

Заранее большое спасибо:)

Обновление 1:

Я попытался использовать CComBSTR в соответствии с предложением вместо необработанного BSTR, инициализированного с использованием прямой CString и исключив SysFreeString (). Но из-за моей проблемы при выходе из области видимости система вызывает SysFreeString(), что снова вызывает сбой:(

Обновление 2: с тем же CComBSTR, который я пытался выделить с помощью SysAllocString(), проблема остается той же:(

Обновление 3: я устал от всех вариантов, и в мире я имею в виду только вопрос

Необходимо ли освобождать BSTR через SysFreeString(), который был выделен с помощью SysAllocString()/string.AllocSysString()?

Обновление 4: я пропустил, чтобы предоставить информацию о сбое. Когда я попытался отладить, COM-сервер упал с ошибкой, говоря

"Возможное повреждение кучи"

, Пожалуйста, помогите мне отсюда..:(

2 ответа

Решение

Наконец, я нашел реальную причину повреждения кучи, которое произошло в коде.

Метод put_StreetName/put_CityName объекта IAddress/CAddress разработан следующим образом.

STDMETHODIMP CAddress::put_CityName(BSTR bstrCityName)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    m_sCityName.Empty();
    TrimBSTR(bstrCityName);
    m_sCityName = ::SysAllocString(bstrCityName);

    return S_OK;
}

BSTR CAddress::TrimBSTR(BSTR bstrString)
{
    CString sTmpStr(bstrString);
    sTmpStr.TrimLeft();
    sTmpStr.TrimRight();
    SysReAllocString(&bstrString,sTmpStr);  // The Devilish Line
}

Дьявольская строка кода - настоящий преступник, который заставил Память пойти в ад.

Что вызвало проблемы?

В этой строке кода строка BSTR, передаваемая в качестве параметра, получена из другого приложения, а реальная память находится в другой области. Таким образом, система пытается перераспределить строку. Либо успешно, либо нет, то же самое пытаются очистить из памяти в исходном приложении / области, вызывая тем самым сбой.

Что еще не решено?

Почему один и тот же кусок кода не падает ни разу в Win XP и более старых системах?:(

Спасибо всем, кто нашел время, чтобы ответить и решить мою проблему:)

// Now All Things are packed in to the Object
obj.Name = bstrName;
obj.Name2 = bstrname2;

Я не совсем понимаю, что вы имеете в виду, говоря, что вещи упакованы, поскольку вы просто копируете указатели на строки, и в тот момент, когда вы вызываете SysFreeString, obj.Name и obj.Name2 будут указывать на недопустимый блок памяти, Хотя этот код небезопасен, похоже, что источником вашей проблемы является класс CFoo. Вы должны показать нам более подробную информацию о вашем коде

Я предлагаю вам использовать класс CComBSTR, который возьмет на себя ответственность за освобождение памяти.

ОБНОВИТЬ

#include <atlbase.h>
using namespace ATL;
...
{
    CComBSTR bstrname(_T("Some Name")); 
    CComBSTR bstrname2(_T("Another Name"));
    // Here one may work with these variables if needed
    ...
    // Copy the local values to the Obj's member Variable 
    bstrname.Copy(&obj.Name); 
    bstrname2.Copy(&obj.Name2);
}

ОБНОВЛЕНИЕ2 Прежде всего нужно освободить bstrCity и bstrStreetName с помощью SysFreeString или использовать CComBSTR вместо этого в этом блоке:

if (SUCCEEDED(hr))
{   
    BSTR bstrStreet = ::SysAllocString(table.m_pRecordData->Street);
    pAddress->put_StreetName(bstrStreet);

    BSTR bstrCity = ::SysAllocString(table.m_pRecordData->City);
    pAddress->put_CityName(bstrCity);

    // SysFreeString(bstrStreet)
    // SysFreeString(bstrCity)
} 

Рассмотрим возможность усиления условия цикла! IRet с iCount

for(...; !iRet /* && (iCount < lRecCount) */; ...)

Также здесь:

m_sCityName = ::SysAllocString(bstrCityName);

Вы выделяете память, но никогда не освобождаете ее, поскольку внутренне CComBSTR& operator = (OLESTR ..) выделяет само новое хранилище. Надо переписать так:

m_sCityName = bstrCityName;

Все остальное, выглядит хорошо для меня

ОБНОВЛЕНИЕ3 Ну, повреждение кучи часто является следствием записи некоторых значений вне выделенного блока памяти. Допустим, вы выделили массив длиной 5 и поместили какое-то значение в 6-ю позицию

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