- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在我的应用程序中,我连接了各种用于创建 COM 对象的函数(例如 CoCreateInstanceEx
),以便在创建某个对象时得到通知。我正在跟踪 std::list
中所有创建的对象我正在遍历该列表以执行各种操作(例如检查哪些 OLE 对象已被激活)。
问题在于,现在,无论何时添加 IUnknown
指向我的列表的指针,我调用 IUnknown::AddRef
以确保它在我跟踪它时不会被破坏。但这不是我真正想要的。对象的生命周期应该与没有我的跟踪代码一样长(或短),所以我宁愿维护一个 weak reference在物体上。每当对某个跟踪的 COM 对象的最后引用被删除(因此该对象被破坏)时,我想得到通知以便我可以更新我的簿记(例如,通过将列表中的指针设置为 NULL
).*
最好的方法是什么?现在,我正在修补所有已创建对象的(第一个)VTable,以便调用 IUnknown::Release
通过第一个 vtable 得到通知。但是,这不适用于从多个接口(interface)(因此具有多个 vtable)继承的 COM 接口(interface),但我不确定这是否真的是一个问题:鉴于 Rules for Implementing QueryInterface , IUnknown::QueryInterface
应该总是只返回一个 IUnknown
, 正确的?所以我可以这样做,然后修补那个 vtable。
此外,这种方法也有点麻烦,因为它涉及创建生成一些代码的 thunk。到目前为止,我只为 32 位实现了这个。不是什么大问题,但仍然存在。
我真的想知道是否没有更优雅的方法来对 COM 对象进行弱引用。有人知道吗?
*:接下来我要解决的问题是在我有事件的迭代器(我正在使用自定义迭代器对象)遍历 COM 对象列表的情况下使其正常工作。我可能需要跟踪事件的迭代器,一旦最后一个迭代器完成,从列表中删除所有空指针。或者类似的东西。
最佳答案
这不是一个答案,而是一系列问题,为什么这是一件非常棘手的事情 - 我将其作为答案,因为这里的信息太多而不适合评论:)
我的理解是,弱引用的概念在 COM 中是不存在的。您已经通过 IUnknown 获得了引用计数,这就是 COM 如何处理对象生命周期管理的总和。严格来说,除此之外的任何东西都不是 COM。
(.Net 确实支持这个概念,但它有一个实际的基于 GC 的内存管理器来提供适当的支持,并且可以将 WeakRef 对象与内存中的常规引用区别对待。但是对于 COM 非常简单的世界,情况并非如此假设,这是一个纯内存和指针的世界,仅此而已。)
COM 指定引用计数是每个接口(interface)的;为了方便起见,任何 COM 对象都可以自由地对每个对象进行 ref 计数,但结果是,如果要包装对象,则必须假设最严格的情况。因此,您不能假设任何给定的 IUnknown 都将用于该对象上的所有 addrefs/releases:您确实需要单独跟踪每个接口(interface)。
规范的 IUnknown - 您通过 QI'ing for IUnknown 返回的那个 - 可以是任何接口(interface) - 甚至是仅用于充当身份的专用 IUnknown! - 只要每次都返回相同的二进制指针值。所有其他接口(interface)都可以以任何方式实现;通常每次都返回相同的值,但是 COM 对象可以合法地在每次有人 QI 的 IFoo 时返回一个新的 IFoo。或者甚至保留 IFoos 的缓存并随机返回一个。
...然后您需要处理聚合 - 基本上,COM 根本没有强大的对象概念,它都是关于接口(interface)的。在 COM 中,对象只是碰巧共享相同规范 IUnknown 的接口(interface)的集合:它们可能在幕后被实现为单个 C/C++ 对象,或者作为呈现一个外观的一系列相关 C/C++ 对象。 '单个 COM 对象'。
说了这么多,考虑到:
I'm tracing the state of various components (including all COM objects) of this software for the sake of debugging
这是一种替代方法,可能会产生一些有用的数据进行调试。
这里的想法是 COM 对象的许多实现会将引用计数作为返回值返回给 Release() - 所以如果它们返回 0,那么这就是接口(interface)可能已被释放的线索。
但不能保证:如 MSDN状态:
The method returns the new reference count. This value is intended to be used only for test purposes.
(添加了重点。)
但这显然是你在这里所做的。
因此,假设您拥有调用代码,您可以做的一件事是用一个名为 MyRelease() 的内联或类似调用 release 的内联替换 Release() 调用,如果它注意到返回值为 0,然后注意到接口(interface)指针现在可能已被释放 - 将其从表中删除,将其记录到文件中,等等。
一个主要的警告:请记住,COM 没有弱引用的概念,即使您尝试将某些东西组合在一起。就 COM 而言,使用未经过 AddRef() 处理的 COM 接口(interface)指针是非法的;因此,如果您将接口(interface)指针值保存在任何类型的列表中,那么您唯一应该这样做的是将它们视为不透明的数字以进行调试(例如,将它们记录到文件中,以便您可以将创建与销毁相关联,或跟踪你有多少优秀的),但不要试图将它们用作实际的接口(interface)指针。
同样,请记住,没有什么要求 COM 对象遵循返回 refcount 的约定;因此请注意,您可能会看到一些看起来像错误但实际上只是 Release 的实现,只是碰巧总是返回 0(或者 rand(),如果你特别不走运的话!)
关于c++ - 如何在 C++ 中维护对 COM 对象的弱引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6120854/
我一直在尝试编写我自己的弱/强指针,但我并不清楚其中的关系。我似乎遇到的所有事情都没有说清楚,而且一个医生经常会反驳另一个医生所说的话。任何人都可以详细解释弱/强指针关系,也许还有图像或代码示例吗?
静态/动态和强/弱类型之间有什么区别? 最佳答案 静态/动态类型涉及何时获取类型信息(在编译时或运行时) 强/弱类型是关于如何严格区分类型(例如,语言是否尝试从字符串到数字进行隐式转换)。 请参阅wi
我有一个非常奇怪的情况。我的服务器当前已关闭并收到 503 http 状态代码。基于如下给定的代码,代码进入 if 条件,但是当我将调试点置于 let error = self?.decodeErro
对于短期运行的操作,避免[weak self]是否可以接受?例如,URLSession 将保留 dataTask(with:completion:) 的闭包: final class ViewCont
我有一个非常奇怪的情况。我的服务器当前已关闭并收到 503 http 状态代码。基于如下给定的代码,代码进入 if 条件,但是当我将调试点置于 let error = self?.decodeErro
假设我有以下情况: Test1.java import java.lang.ref.WeakReference; public class Test1 { public WeakReferen
有没有办法告诉模拟器(我正在使用 Modelsim)当信号不是由任一双向接口(interface)驱动时将信号拉到弱“H”? 例如,如果我有一个 I2C 信号 I2C_SDA 被声明为来自 2 个模块
这是将一些值放入 WeakHashMap 中然后从映射中删除这些值的代码片段。它如何处理分配的内存? import java.util.*; public class WeakHashMap_Main
我正在尝试弄清楚智能指针可以实现什么。 但有一些感觉像是障碍。 普通指针有一个简短的定义 Someclass *p但是智能指针有点长shared_ptr p当您必须处理这些指针的模板(如 vector
这两行代码有区别吗? __weak IBOutlet UITextField *usernameField; @property (weak) IBOutlet UITextField *userna
我最近发现了 WeakHashMap Java 中的数据结构。 但是,我不明白它在不再正常使用时对映射进行垃圾收集是什么意思。数据结构如何知道我将不再在我的程序中使用 key ?如果长时间不引用 ke
我的问题是为什么 weak IBOutletCollection 总是 nil?如果将弱变强,我所有的按钮都在那里,这真的很奇怪。我试图理解苹果的逻辑,我看不出单个按钮和一组按钮在内存管理方面没有区别
我创建一个 WeakHashMap 为 WeakHashMap map = new WeakHashMap(); map.put(emp,"hello"); 其中 emp 是一个 Employee 对
在delphi sydney中,在对象(不是接口(interface))前面设置[weak]会受到惩罚吗?示例: TMyObject = class(Tobject) Private
在delphi sydney中,在对象(不是接口(interface))前面设置[weak]会受到惩罚吗?示例: TMyObject = class(Tobject) Private
众所周知,我们将声明一个可以打破强引用循环的弱委托(delegate)对象: // MyObject.h ... @property (nonatomic, weak) id delegate; ..
我已阅读this article关于Java中不同类型的引用(强引用、软引用、弱引用、幻像引用),但我不太理解。 这些引用类型之间有什么区别?每种类型何时使用? 最佳答案 Java 提供了两种不同类型
我突然想到...我相信弱引用的生命 与该引用的范围(在函数内或全局内)相关。 所以我想知道,只要我将数据处理保持在特定范围内,那么我应该可以使用 weak 与 strong 引用。正确的? 我问的原因
func addAdditionalElement(_ additionalSelectedElementsIDs: [String], startX: CGFloat, containerView:
我想要一个指针,以便我可以判断引用计数何时为 1。本质上,指针的工作方式类似于 weak_ptr,但清理工作需要手动进行。也就是说,程序每隔一段时间就会经历一个指针循环,并检查哪些指针只剩下一个引用。
我是一名优秀的程序员,十分优秀!