다음 이벤트가 포함 된 IE7/8 HTML 페이지에 ActiveX 컨트롤이 있습니다. [id(1)] HRESULT MessageReceived([in] BSTR id, [in] BSTR json)
. Windows에서 이벤트는 OCX.attachEvent("MessageReceived", onMessageReceivedFunc)
으로 등록됩니다.개체 태그의 IE attachEvent로 인해 메모리 손상이 발생합니다.
다음 코드는 HTML 페이지에서 이벤트를 발생시킵니다. I는 애플리케이션 검증 부와 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;
}
후 다음 비정상적인 동작이 수행 자바 스크립트 콜백을 실행하고()를 호출, pvars에서 BSTR은 [1] pvars 복사 후 [0]에 대한 어떤 알려지지 않은 이유!? pvars의 delete []는 동일한 문자열을 두 번 비우고 힙 손상으로 끝나게합니다.
아무도 아이디어가 있습니까? 이것은 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;
}
고마워요!
광범위한 의견을 보내 주셔서 감사합니다. "delete [] pvars;" 내 두 번째 코드 예제에서는 복사 실수였습니다. 우리가 사용하는 구현에 상관없이 Invoke() 메모리가 말하기 전에 문제의 근원이 있습니다 : pvars [0] = "a"; pvars [1] = "b"; ... Invoke() 메모리가 나온 후 ... pvars [0] = "b"; pvars [1] = "b"; ... 누군가가 배열의 문자열을 복사했습니다. 나는 IE가 이것을하고 있다고 생각한다. 예, 우리는 CComVariant * 대신 VARIANT를 사용하여 코드 또는 두 번째 코드 (delete [] pvars 제외)로 메모리 손상을 피할 수 있습니다. 그러나 문자열은 여전히 attachEvent()를 사용할 때만 잘못 복사됩니다. – Lars
Andrew W. Troelsen의 "Developer 's Workshop to COM and ATL 3.0"과 같은 모든 실수가있는 것 같습니다. 이 책의 적어도 하나의 예는 topic 초보자의 코드와 똑같이 생겼습니다 (그리고 위에서 언급 한 모든 발행물을 가지고 있습니다). – vond