使用:: SysFreeString()释放BSTR。更多平台依赖? [英] Freeing a BSTR using ::SysFreeString(). More Platform Dependant?

查看:358
本文介绍了使用:: SysFreeString()释放BSTR。更多平台依赖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个COM服务器,它有很多接口和方法。大多数方法具有BSTR作为参数和用作返回的局部参数。一个代码段看起来像



更新5:



这将从基于特定条件的数据库中提取数据以填充对象数组。

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

//检查数据库服务器连接

COleSafeArray saAddress;
HRESULT hr;

//准备SQL字符串dan查询DB

long lRecCount = table.GetRecordCount();

if(lRecCount> 0)
{
//为放置细节创建一维安全数组
saAddress.CreateOneDim(VT_DISPATCH,lRecCount);

IAddress * pIAddress = NULL;
//检索细节
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 CComBSTR类型
m_sCityName.Empty(); //释放旧字符串
m_sCityName = :: SysAllocString(bstrCityName); //为新字符串创建内存
return S_OK;
}

问题出在内存释放部分。该代码在任何Win XP机器中工作非常好,但是当涉及到WIN2K8 R2和WIN7代码崩溃,并指向:: SysFreeString()作为罪魁祸首。 MSDN不足以解决问题。



任何人都可以帮助找到正确的解决方案?



提前感谢:)



更新1: >

我已经尝试使用CComBSTR按照建议在原始BSTR的地方,使用直接CString初始化和排除SysFreeString()。但是对于我的麻烦,在超出范围,系统调用SysFreeString(),它再次导致崩溃:(



Update 2:
使用相同的CComBSTR我试图使用SysAllocString()分配,问题仍然相同:(



更新3:
我厌倦了所有的选项,在和平我只有问题的心情


是否有必要释放BSTR SysFreeString()是使用SysAllocString()/ string.AllocSysString()分配


更新4:
我错过提供有关崩溃的信息当我试图调试COM服务器崩溃时出现错误


可能的堆损坏


请帮助我离开..:(


IAddress / CAddress的put_StreetName / put_CityName以下列方式设计。

  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字符串另一个应用程序和真实内存在另一个领域。所以系统正在尝试重新分配字符串。不管是否成功,都会尝试在原始应用程序/领域中从内存中清除,从而导致崩溃。



仍然未解决的问题? strong>


为什么同一块代码在Win XP和
旧系统中没有崩溃? :(


感谢所有花时间回答和解决我的问题的人:)


I am writing a COM Server which have a plenty of Interfaces and methods. And most of the methods have the BSTR as the parameters and as local parameters used for the return. A snippet looks like

Update 5:

The real code. This fetches from bunch of Data based on a specific condition the DB to populate an array of Object.

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;
}

The problem lies in the Memory Freeing part. The code works very fine in any Win XP machines, but when comes to WIN2K8 R2 and WIN7 the code crashes and pointing to the ::SysFreeString() as the culprit. The MSDN is not adequate to the solution.

Can anyone please help in finding the right solution?

Thanks a lot in advance :)

Update 1:

I have tried using the CComBSTR as per the suggestion in the place of raw BSTR, initialized using direct CString's and excluded the SysFreeString(). But for my trouble, on getting out of scope the system is calling the SysFreeString() which again causes the crash :(

Update 2: With the same CComBSTR i tried to allocate using the SysAllocString() , the problem remains same :(

Update 3: I am tired of all the options and in peace I am having only question in mind

Is it necessary to free the BSTR through SysFreeString() which was allocated using SysAllocString()/string.AllocSysString()?

Update 4: I missed to provide the information about the crash. When I tried to debug the COM server crashed with a error saying

"Possible Heap Corruption"

. Please help me out of here.. :(

解决方案

Finally I have found the real reason for the Heap Corruption that happened in the code.

The put_StreetName/put_CityName of the IAddress/CAddress is designed in a following way.

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
}

The Devilish Line of code is the real culprit that caused the Memory to go hell.

What caused the trouble?

In this line of code, the BSTR string passed as a parameter is from another application and the real memory is in another realm. So the system is trying to reallocate teh string. Either succeed or not, the same is tried to cleared off from the memory in original application/realm, thus causing a crash.

What still unsolved?

Why the same piece of code doesn't crashed a single time in Win XP and older systems? :(

Thanks for all who took their time to answer and solve my problem :)

这篇关于使用:: SysFreeString()释放BSTR。更多平台依赖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆