【问题标题】:Why are all references to my IDispatch object not released?为什么没有释放对我的 IDispatch 对象的所有引用?
【发布时间】:2011-08-18 13:07:06
【问题描述】:

我在我的 C++ 程序中托管一个 IWebBrowser2 控件,只使用普通的 Win32(没有 mfc、atl、wtl 等)。在 DISPID_NAVIGATECOMPLETE2 上,我添加了一个自定义对象,可从显示的网页上运行的 javascript 访问。

要添加自定义对象,我使用 DISPATCH_PROPERTYPUT 调用 InvokeEx 和带有指向自定义对象的指针的 DISPARAMS 结构。

在调用 InvokeEx 期间,我的自定义对象的 AddRef 函数被调用,并且我增加了它的引用计数器。但是对象永远不会调用它的 Release 函数,所以引用计数器永远不会再减少到零。

在 InvokeEx 中调用 AddRef() 后谁负责调用 Release()?

编辑:(添加一些代码)

这是将我的自定义对象添加到 IHTMLWindow2 的代码。 custObj 指向我的自定义对象

IHTMLWindow2 *win = NULL;
GetDoc()->get_parentWindow(&win);
IDispatchEx *winEx = NULL;
win->QueryInterface(&winEx);

DISPID dispid;
HRESULT hr = winEx->GetDispID(objName, fdexNameEnsure, &dispid); //objName is "JSObject"

DISPID namedArgs[] = {DISPID_PROPERTYPUT};
DISPPARAMS params;
params.rgvarg = new VARIANT[1];
params.rgvarg[0].pdispVal = custObj;
params.rgvarg[0].vt = VT_DISPATCH;
params.rgdispidNamedArgs = namedArgs;
params.cArgs = 1;
params.cNamedArgs = 1;

hr = winEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL); 

这是我要添加的对象(为简洁起见,省略了一些私有成员)

class JSObject : public IDispatch {
private:
    long ref;
public:
    JSObject();

    // IUnknown
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    // IDispatch
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid,
        ITypeInfo **ppTInfo);
    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid,
        LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
    virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid,
        LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
        EXCEPINFO *pExcepInfo, UINT *puArgErr);
};

编辑 2:

现在它似乎可以正常工作了,我应该决定把它放在 github 上。

https://github.com/Tobbe/CppIEEmbed。如果可以的话,请分叉和改进:)

【问题讨论】:

  • 准确记录您分配的属性。顺便说一句,它应该是 DISPATCH_PROPERTYPUTREF,因为您正在分配一个对象。
  • 如果我使用 DISPATCH_PROPERTYPUTREF InvokeEx 失败并显示 DISP_E_MEMBERNOTFOUND
  • @Hans Passant:当您说“准确记录您分配的属性”时,我不完全确定您的要求。我添加到问题中的代码是否满足您的要求?
  • dispid的值是多少?
  • 真实代码是否包含任何错误检查?我很难相信这会奏效。这当然可以解释问题。

标签: c++ winapi com iwebbrowser2 idispatch


【解决方案1】:

嗯,你是在分配一个属性,不是吗?只要此属性存在并引用您的对象,它就会添加一个引用。

如果您希望远程对象释放您的引用,您应该将 NULL 分配给属性或其他对象。

【讨论】:

  • 我应该在我的问题中说明这一点,但问题是即使“远程对象”被破坏,我的引用也不会被释放。它不应该在死前释放所有分配的属性吗?
  • 我应该。但是你确定远程对象真的被破坏了,并且没有其他的引用在附近晃来晃去吗?
  • 我没有正确释放远程对象,所以它永远不会被破坏。由于它从未被销毁,因此它保留了对我的自定义对象(我的 JSObject 实例)的引用。
猜你喜欢
  • 1970-01-01
  • 2010-10-25
  • 2011-11-18
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
相关资源
最近更新 更多