忍不住还是要发篇文章:关于VC6中(VARIANT)BSTR传入传出发生RtlSizeHeap(user breakpoint at address)的问题
2006-06-23 11:16
741 查看
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 );
}
//...
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 );
}
//...
相关文章推荐
- MFC重现"User Breakpoint called from code at"错误——CString在多线程中容易导致的问题
- Invalid address specified to RtlGetUserInfoHeap( 00670000, 0067D558 )
- User breakpoint called from code at XXX 问题分析汇总
- 解决VC++“User breakpoint called from code at XXX”问题
- 刚刚开始用ATL写COM组件,遇到RtlSizeHeap问题
- 关于jvm内存分配的问题heap size [268435456] not equal to maximum heap size [2147483648],需要修改的jvm配置
- 关于“user breakpoint called from code at..”错误
- 对 User breakpoint called from code at XXX 问题分析汇总
- 调试: 解决跨进程时使用CString报错的问题, [Invalid Address specified to RtlFreeHeap]
- 关于heapsize & heapgrowthlimit
- 现代软件工程系列 学生的精彩文章 (5) 其实还是人的问题
- PHP关于VC11,VC9,VC6以及Thread Safe和Non Thread Safe版本选择的问题
- 关于shiro后台权限改动,重新登录后发现权限还是以前的问题的解决
- 关于oracle设置不活动自动断开连接导致java访问数据库时发生异常的问题
- 关于分页 使用pageNum还是offset的问题
- 关于vector的size()的使用问题
- Access violation at address 问题与解决方法
- 关于“解决实现注册用户后,自动具备访问网站的权限的问题”文章中配置出现找不到角色的问题的解决办法
- 关于Textview maxline=1 ellipsize="end" 导致中英文数字混合分割错误的问题
- [转]PHP关于VC9和VC6以及Thread Safe和Non Thread Safe版本选择的问题