我在嵌入IE7/8 HTML页面中有一个ActiveX控件,该页面有以下事件[id(1)] HRESULT MessageReceived([in] BSTR id, [in] BSTR json)
。在Windows上,该事件已注册OCX.attachEvent("MessageReceived", onMessageReceivedFunc)
。对象标记上的IE attachEvent导致内存损坏
以下代码在HTML页面中触发事件。我启用gflags.exe与应用验证
HRESULT Fire_MessageReceived(BSTR id, BSTR json)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
CComVariant* pvars = new CComVariant[2];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
pvars[1] = id;
pvars[0] = json;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
delete[] pvars; // -> Memory Corruption here!
return varResult.scode;
}
后,以下奇怪的行为发生: 调用()正在执行的JavaScript回调,从pvars的BSTR [1]被复制到pvars后[0]为一些未知的原因!? pvars的delete []会导致没有相同字符串的double,然后以堆损坏结束。
有没有人知道这里发生了什么?这是一个IE错误还是我错过了OCX实现中的一个窍门?
如果我使用像标签:
<script for="OCX" event="MessageReceived(id, json)" language="JavaScript" type="text/javascript">
window.onMessageReceivedFunc(windowId, json);
</script>
...不会出现奇怪的复制操作。
由于Fire_MessageReceived()的调用者负责释放BSTR,因此下面的代码似乎也没问题。
HRESULT Fire_MessageReceived(BSTR srcWindowId, BSTR json)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
VARIANT pvars[2];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
pvars[1].vt = VT_BSTR;
pvars[1].bstrVal = srcWindowId;
pvars[0].vt = VT_BSTR;
pvars[0].bstrVal = json;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
delete[] pvars;
return varResult.scode;
}
谢谢!
感谢您的广泛评论! “删除[] pvars;”在我的第二个代码示例中是一个复制错误。 无论我们使用哪个实施方式中,问题的根源在于,前调用()存储表示: pvars [0] =“A”; pvars [1] =“b”; ...调用后()内存说... pvars [0] =“b”; pvars [1] =“b”; ...所以有人已经复制了数组中的字符串。我想IE是这样做的。 是的,我们可以用VARIANT,而不是CComVariant的避免您的代码或我的第二个代码中的内存破坏(不删除[] pvars)*。但是,仅当使用attachEvent()时,字符串仍然被错误地复制。 – Lars 2010-06-17 09:57:42
看起来所有的错误都来自以下书籍:Andrew W. Troelsen的“COM和ATL 3.0开发者研讨会”。本书中至少有一个例子看起来与主题起始者的代码完全相同(并且具有上面提到的所有主题)。 – vond 2015-01-15 04:53:56