我在嵌入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