忍不住还是要发篇文章:关于VC6中(VARIANT)BSTR传入传出发生RtlSizeHeap(user breakpoint at address)的问题

As it turns out, I was able to determine why I was getting this RTLSizeHeap problem. Being a novice to COM and ATL, I had a class that stored a string (_bstr_t) value. As you would expect, I had the normal get_ and put_ functions to operate on the member. The problem was, my get_ did not send back a copy of the string held onto by the _bstr_t member that I had set up. All I did was assign it (thinking the operator = function actually makes a copy). Since I was using smart pointers, I had the result of the get_ function assigned to another _bstr_t. The problem...both _bstr_t values were looking at the same memory. So no problem would occur when the first object goes out of scope as the first _bstr_t frees the memory it was holding, but when the second object would go out of scope...bam RtlSizeHeap problem - since the second _bstr_t was still pointing to memory that was now freed. To solve this, my get_ function was changed to:

STDMETHODIMP CSomeClass::get_m_sToTime(BSTR *pVal)
{
AFX_MANAGE_STATE(AfxGetAppModuleState())
if (pVal)
*pVal = bstrtToTime.copy();
return S_OK;
}

Summary - RtlSizeHeap is definitely not lying - Most certainly this error is the result of BSTRs and _bstr_t variables not being handled appropriately. Double and tripple check your code - It took me a long time to find this!

Hope this helps!
Dan
//以上是老外的说法,有道理

我的问题:在external(自定义浏览器控件)中要向javascript中输出一个字符串,我原来的做法是if(pVarResult) *pVarResult=CComVariant(_T"myOutString");而CComVariant会自动回收heap上的空间。所以问题出现在=号上。*pVarResult是一个VARIANT结构变量,程序中又没有重载该类型的=操作,于是bstrVal指向CComVariant中的bstrVal,而CComVariant自动回收了,因此,js中的接收变量的值便不可预料,并且,在js退出该变量的生存空间时,要回收该变量的空间,于是出错。这个问题在MSDN中说得已经很明白,可惜没想到,走了一大堆弯路。

当创建 BSTR 并在 COM 对象之间传递它们时,必须小心地处理它们所使用的内存以避免内存泄漏。当 BSTR 停留在接口中时,在完成其使用后必须释放出它的内存。但是,如果 BSTR 传递出了接口,那么接收对象将负责它的内存管理。
一般情况下,分配和释放分配给 BSTR 的内存的规则如下:
当调用进来一个需要 BSTR 参数的函数时,必须在调用之前为 BSTR 分配内存,并且在完成操作之后将其释放。例如:
HRESULT IWebBrowser2::put_StatusText( BSTR bstr );

// shows using the Win32 function
// to allocate memory for the string:
BSTR bstrStatus = ::SysAllocString( L"Some text" );
if (bstrStatus == NULL)
   return E_OUTOFMEMORY;

pBrowser->put_StatusText( bstrStatus );
// Free the string:
::SysFreeString( bstrStatus );
//...
当调用进来一个返回 BSTR 的函数时,必须自己来释放字符串。例如:
HRESULT IWebBrowser2::get_StatusText( BSTR FAR* pbstr );
//...
BSTR bstrStatus;
pBrowser->get_StatusText( &bstrStatus );

// shows using the Win32 function
// to freee the memory for the string:
::SysFreeString( bstrStatus );
当实现返回 BSTR 的函数时,请分配字符串,但不要释放它。接收函数会释放内存。例如:
// Example shows using MFC's
// CString::AllocSysString

//...
HRESULT CMyClass::get_StatusText( BSTR * pbstr )
{

   try
   {
      //m_str is a CString in your class
      *pbstr = m_str.AllocSysString( );
      }
   catch (...)
   {
      return E_OUTOFMEMORY;
   }

// The client is now responsible for freeing pbstr.
return( S_OK );
}
//...

阅读更多
个人分类: 编程:C++/VC
上一篇CSDN问题太多,作为CSDN的一个用户,我感到非常遗憾
下一篇自定义浏览器控件中去除默认IE右键菜单中的垃圾项(如百度XXX搜索)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭