次のイベントがある埋め込みIE7/8HTMLページ内にActiveXコントロールがあります[id(1)] HRESULT MessageReceived([in] BSTR id, [in] BSTR json)
。Windowsでは、イベントはに登録されOCX.attachEvent("MessageReceived", onMessageReceivedFunc)
ます。
次のコードは、HTMLページでイベントを発生させます。
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;
}
アプリケーションベリファイアでgflags.exeを有効にすると、次の奇妙な動作が発生します。JavaScriptコールバックを実行しているInvoke()の後、何らかの理由でpvars[1]のBSTRが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;
}
ありがとう!