S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

关于COM组件在IE的析构问题

Posted on 2009-09-14 15:01 S.l.e!ep.¢% 阅读(1505) 评论(1)  编辑 收藏 引用 所属分类: COM

为了实验,写了一个COM组件嵌入HTML,大概功能是接收服务器的数据,并显示出来

HTML 调用COM组件的代码大概是这样的:

<html>
<SCRIPT LANGUAGE="JavaScript">
<!-- 
 function onRecvData()
 {
       try
       {
           var obj_Connection = new ActiveXObject("MyObj.MyObj.1");

           obj_Connection.OnRecv = function onRecv(buf, len)
          {
              testbox.value = buf;
          } ;

           obj_Connection.init(12345); 
        }
        catch(e)
        {
           var strErrMsg;
           strErrMsg = "Error: " + e.message;
           alert(strErrMsg);
        }
    }

//-->
</SCRIPT>

</HEAD>

<BODY>
<input onClick="onRecvData();" type="button" value="Go">
<input type="text" id = testbox>
</BODY>
</html>

COM组件在接收到SOCKET的数据之后,就会调用
void CMyObj::onReceive(const char* pData, int nLen)
{
 if ( m_pfnRecv != NULL )
 {
  CComVariant* pvars = new CComVariant[2];
   
  pvars[1] = pData;
  pvars[0] = nLen; 
  
  DISPPARAMS disp = { pvars, NULL, 2, 0 };
  HRESULT hr = m_pfnRecv->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
  delete[] pvars;
  
 }// if ( m_pfnRecv != NULL )
}

其中的 m_pfnRecv 就是通过 STDMETHODIMP CMyObj::put_OnRecv(IDispatch *newVal) 的方法设置进去的
发现在调用几十次(大约80次左右后),COM组件会出错(访问的地址不可读),出错堆栈大约如下:

First-chance exception in IEXPLORE.EXE (JSCRIPT.DLL): 0xC0000005: Access Violation.

JSCRIPT! 75bc4a27()
JSCRIPT! 75bc7564()
JSCRIPT! 75bc7414()
JSCRIPT! 75bc678e()
CMyObj::onReceive(const char * 0x0012e40c, int 260) line 64 + 44 bytes

想了很久,没想出好的解决方法,一直在怀疑是否是 m_pfnRecv->Invoke 调用的问题
于是乎做了以下的实验:

将HTML调用COM组件的代码改为:
<html>
<SCRIPT LANGUAGE="JavaScript">
<!-- 

function onRecv(buf, len)
{
       testbox.value = buf;
} ;

 function onRecvData()
 {
       try
       {
           var obj_Connection = new ActiveXObject("MyObj.MyObj.1");

           obj_Connection.OnRecv = onRecv;
           obj_Connection.init(12345); 
        }
        catch(e)
        {
           var strErrMsg;
           strErrMsg = "Error: " + e.message;
           alert(strErrMsg);
        }
    }

//-->
</SCRIPT>

</HEAD>

<BODY>
<input onClick="onRecvData();" type="button" value="Go">
<input type="text" id = testbox>
</BODY>
</html>

改完之后,又发现另一问题
在调用几十次之后,它会走到 CMyObj 的析构
 ~CMyObj()
 {
 }

每次点击 Go 按钮, 它都会执行几十次后,就析构

于是乎,再改了下HTML ,将 obj_Connection 改为全局变量

<html>
<SCRIPT LANGUAGE="JavaScript">
<!-- 

var var obj_Connection;

function onRecv(buf, len)
{
       testbox.value = buf;
} ;

 function onRecvData()
 {
       try
       { 
           obj_Connection = new ActiveXObject("MyObj.MyObj.1");

           obj_Connection.OnRecv = onRecv;
           obj_Connection.init(12345); 
        }
        catch(e)
        {
           var strErrMsg;
           strErrMsg = "Error: " + e.message;
           alert(strErrMsg);
        }
    }

//-->
</SCRIPT>

</HEAD>

<BODY>
<input onClick="onRecvData();" type="button" value="Go">
<input type="text" id = testbox>
</BODY>
</html>


这下终于正常了,只有每当按 F5去刷新页面的时候,才会调用到 MyObj 的析构
需要再细究下原因。

Feedback

# re: 关于COM组件在IE的析构问题  回复  更多评论   

2009-10-15 12:07 by tailorcai
你的obj_Connection被GC了呗。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理