另外还有如下一段代码,如果把BSTR bstr=SysAllocString(OLESTR("&nbsp"))换成bstr=SysAllocString(OLESTR("")),将在执行SafeArrayDestroy(sfArray)时崩溃。IHTMLDocument2 *document; 
0Aif(SUCCEEDED(HrGetDoc(&document)))
{
HRESULT hresult = S_OK;
VARIANT *param;
SAFEARRAY *sfArray;
BSTR bstr = SysAllocString(OLESTR("&nbsp"));<==如果把此处的串换成""// Creates a new one-dimensional array
sfArray = SafeArrayCreateVector(VT_VARIANT, 0, 1);if (sfArray == NULL || document == NULL) {
goto cleanup;
}hresult = SafeArrayAccessData(sfArray,(LPVOID*) & param);
param->vt = VT_BSTR;
param->bstrVal = bstr;
hresult = SafeArrayUnaccessData(sfArray);
hresult = document->write(sfArray);
0Adocument->close();
document->Release();
cleanup:
SysFreeString(bstr);
if (sfArray != NULL) {
SafeArrayDestroy(sfArray);〈=在这里崩溃。
}
}
========================
欢迎光临我的网站:http://vcworm.51.netVC综合性技术网站,介绍MFC、COM、界面控制、网络程序设计、网络协议、.Net框架、Visual Studio .Net、C#等方方面面的知识。本站诚邀各位热心的朋友加盟。一同建设一个有助于程序员的学习交流园地。详情请登录http://vcworm.51.net

解决方案 »

  1.   

    请参考一下这段文章:SafeArrayDestroy
    Destroys an existing array descriptor and all of the data in the array. If objects are stored in the array, Release is called on each object in the array.HRESULT SafeArrayDestroy( 
      SAFEARRAY *  psa  
    );
    Parameter
    psa 
    Pointer to an array descriptor created by SafeArrayCreate. 
    Return Value
    The return value obtained from the returned HRESULT is one of the following.Return value Meaning 
    S_OK Success. 
    DISP_E_ARRAYISLOCKED The array is currently locked. 
    E_INVALIDARG The item pointed to by psa is not a safearray descriptor. // 注意下一段话。
    Res
    Safe arrays of variant will have VariantClear called on each member and safe arrays of BSTR will have SysFreeString called on each element. RecordClear will be called to release object references and other values of a record without deallocating the record.Example
    STDMETHODIMP_(ULONG) CEnumPoint::Release()
    {
       if(--m_refs == 0){
          if(m_psa != NULL)
          SafeArrayDestroy(m_psa);
          delete this;
          return 0;
       }
       return m_refs;
    }我觉得:
    cleanup:
    SysFreeString(bstr);   // 似乎不应该调用这句。因为SafeArrayDestroy会帮你自动执行。
    if (sfArray != NULL) 
    {
    SafeArrayDestroy(sfArray);《==错误发生处
    }
      

  2.   

    zxs218(Frank Zhou) 说的对,当param->bstrVal = bstr时,bstr指向的缓冲区并没有被考贝,只是简单的将bstr的值赋给了bstrVal.所当你用
    SysFreeString(bstr);
    SafeArrayDestroy(sfArray);
    事实上是同一个缓冲区你释放了两次。建议param->bstrVal = bstr改成param->bstrVal = SysAllocString( bstr );或去掉后一句SysFreeString(bstr);
      

  3.   

    谢谢二位。本人对com还不是很熟悉。两位的解答好象确实解决了我的问题。不过,我还有一点不明,请大家继续帮忙。以下代码是从msdn上关于IHTMLDocument2::write的文档中copy下来的(没做任何改动)。按两位的说法,这段代码是否也有错误呢? IHTMLDocument2 *document; // Declared earlier in the code
    HRESULT hresult = S_OK;
    VARIANT *param;
    SAFEARRAY *sfArray;
    BSTR bstr = SysAllocString(OLESTR("Written by IHTMLDocument2::write().")); // Creates a new one-dimensional array
    sfArray = SafeArrayCreateVector(VT_VARIANT, 0, 1);

    if (sfArray == NULL || document == NULL) {
    goto cleanup;
    } hresult = SafeArrayAccessData(sfArray,(LPVOID*) & param);
    param->vt = VT_BSTR;
    param->bstrVal = bstr;
    hresult = SafeArrayUnaccessData(sfArray);
    hresult = document->write(sfArray);cleanup:
    SysFreeString(bstr);   《==释放bstr
    if (sfArray != NULL) {
    SafeArrayDestroy(sfArray);  〈==又要释放bstr
    }
      

  4.   

    我认为是,因为这个错误不是经常发生,只有当bstr指向的随机内存不可访问的时候才会发生。也许作者没有留意到也是可能的。