Это не столько ответ, сколько ряд вопросов, почему это действительно сложная задача - я привожу это как ответ, так как здесь слишком много информации, чем умещается в комментарии:)
Насколько я понимаю, концепция слабой ссылки просто не существует в COM, точка. У вас есть подсчет ссылок через IUnknown, и это общая сумма того, как COM работает с управлением временем жизни объекта. Все остальное, строго говоря, не является COM.
(. Net действительно поддерживает эту концепцию, но у нее есть настоящий диспетчер памяти на основе GC, обеспечивающий соответствующую поддержку, и он может обрабатывать объекты WeakRef иначе, чем обычные ссылки в памяти. Но это не так в очень простом мире COM предполагает, что это мир простой памяти и указателей, и немного больше.)
COM указывает, что подсчет ссылок для каждого интерфейса; для удобства любой COM-объект может выполнять подсчет ссылок для удобства, но в результате вы должны принять наиболее ограничительный вариант. Таким образом, вы не можете предполагать, что любой данный IUnknown будет использоваться для всех адресов / выпусков этого объекта: вам действительно нужно отслеживать каждый интерфейс отдельно.
Канонический IUnknown - тот, который вы возвращаете QI'ing для IUnknown - может быть любым интерфейсом вообще - даже выделенным IUnknown, который используется только с целью действовать как личность! - до тех пор, пока одно и то же значение двоичного указателя возвращается каждый раз. Все остальные интерфейсы могут быть реализованы любым способом; обычно одно и то же значение возвращается каждый раз, но COM-объект может на законных основаниях возвращать новый IFoo каждый раз, когда кто-то QI для IFoo. Или даже держите в кэше IFoos и возвращайте его случайным образом.
... и тогда вам нужно иметь дело с агрегацией - в принципе, в COM вообще нет четкой концепции объекта, все дело в интерфейсах. Объекты в COM - это просто набор интерфейсов, которые совместно используют один и тот же канонический IUnknown: они могут быть реализованы как отдельный объект C / C ++ за кулисами или как семейство связанных объектов C / C ++, представляющих фасад «один COM-объект».
Сказав все это, учитывая, что:
Я отслеживаю состояние различных компонентов (включая все COM-объекты) этого программного обеспечения для отладки.
Вот альтернативный подход, который может дать некоторые полезные данные для отладки.
Идея заключается в том, что многие реализации COM-объектов будут возвращать счетчик ссылок в качестве возвращаемого значения для Release () - поэтому, если они возвращают 0, это признак того, что интерфейс, возможно, был освобожден.
Это не гарантируется, однако: как MSDN состояния:
Метод возвращает новый счетчик ссылок. Это значение предназначено для использования только в целях тестирования.
(выделение добавлено)
Но это, очевидно, то, что вы здесь делаете.
Итак, одну вещь, которую вы могли бы сделать, предполагая, что у вас есть вызывающий код, - это заменить вызовы Release () на встроенный MyRelease () или аналогичный, который вызовет release, и если он заметит, что возвращаемое значение равно 0, затем отмечает, что указатель интерфейса теперь возможно освобожден - удаляет его из таблицы, записывает в файл и т. д.
Одно важное предостережение: имейте в виду, что в COM нет понятия слабой ссылки, даже если вы пытаетесь что-то взломать вместе. Использование указателя интерфейса COM, который не был AddRef () ', является недопустимым для COM; так что если вы сохраняете значения указателя интерфейса в любом виде списка, единственное, что вам следует делать с ними, это рассматривать их как непрозрачные числа для целей отладки (например, записать их в файл, чтобы вы могли соотносить создания с разрушениями или отслеживать сколько у вас есть выдающихся), но не пытайтесь использовать их в качестве фактических указателей интерфейса.
Опять же, имейте в виду, что ничто не требует, чтобы COM-объект следовал соглашению о возврате refcount;так что имейте в виду, что вы можете увидеть что-то похожее на ошибку, но на самом деле это просто реализация Release, которая случается с всегда возвращает 0 (или rand (), если вам особенно не повезло!)