当对象的引用计数为零时

这篇具有很好参考价值的文章主要介绍了当对象的引用计数为零时。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上一篇文章,我提到要避免对象的析构函数被调用两次,有一位读者声称:当对象第一次被构建的时候,它的引用计数应该为 0,在某些时候,例如调用 QueryInterface 的时候,它的 AddRef 方法应该被调用以增加其引用计数。

如果在构造一个对象时将它的引用计数设置为 0,你有点像在玩火柴。对于新手来说,当对象被创建的时候,它的引用计数不应该为 0,因为创建此对象的人拥有这个对象的一个引用。

请记住,对于 COM 对象来说,它的引用计数规则是:当一个函数产生一个引用(通常是一个接口指针)时,引用计数会增加。如果你将构造函数看做是一个函数的话,则它需要增加引用计数的值,来体现它创造了一个对象这样一个事实。

如果你更喜欢玩火柴,你最终可能会用如下代码烧到自己:

>> 请移步至 topomel.com 以查看图片 <<

请注意,在上面的代码中,我们将对象的引用计数初始化为 0。这使你处于与清理对象相同的“边缘区域”,而该对象引用计数为零,因此你会面临相同的问题:

>> 请移步至 topomel.com 以查看图片 <<

在销毁过程中保存自身的对象很可能在创建过程中加载自身。你遇到了完全相同的问题。对 IObjectWithSite::SetSite(this) 的调用会将对象的引用计数从 0 增加到 1,而对 IObjectWithSite::SetSite(NULL) 的调用会将其递减为零。当引用计数递减到零时,这将销毁对象,从而导致对象被 MyObject::Load 方法无意中销毁。

MyObject::Create 静态方法没有意识到这种情况已经发生,并继续调用 QueryInterface 方法以将指针返回给调用方,期望它将引用计数从 0 增加到 1。不幸的是,它正在对已经被摧毁的对象执行此操作。

当你使用引用计数为零的对象时,就会发生这种情况:当你放弃控制权时,它可能会消失。创建的对象应具有 1 的引用计数,而不是零。

ATL更喜欢玩火柴,在其对象构造中使用上述 MyObject::create 函数的道德等价物:

>> 请移步至 topomel.com 以查看图片 <<

ATL 会调用引用计数为零的 FinalConstruct 方法来构造一个 COM 对象。如果你知道这种方式的潜在危险,则可以使用
DECLARE_PROTECT_FINAL_CONSTRUCT 宏将 InternalFinalConstructAddRef 和 InternalFinalConstructRelease 方法更改为在调用 FinalConstruct 期间实际临时增加引用计数的版本,然后在 QueryInterface 调用之前将引用计数放回零(不破坏对象)。

它有效,但在我看来,它过于依赖程序员的警惕性。ATL 的默认设置是将选择权交给程序员,并依靠程序员“知道”FinalConstruct中可能发生危险的事情,并且有意识地要求
DECLARE_PROTECT_FINAL_CONSTRUCT。换句话说,它选择了危险的默认值,程序员必须明确要求安全版本。但是程序员有很多事情要做,强迫他们考虑在 FinalConstruct 方法中执行的每个操作的传递闭包的后果是一个不合理的要求。

考虑我们上面的例子。最初编写代码时,Load 方法可能要简单得多,如下图所示:

>> 请移步至 topomel.com 以查看图片 <<

直到一两个月后,才有人向加载和保存方法添加了站点支持。这个看似简单而孤立的更改,完全遵守了引用计数的 COM 规则,在对象创建和销毁代码路径中产生了连锁反应。如果在 FinalConstruct 和 Load 之间放置四个级别的函数调用,那么这种第四级调用器效应很容易被忽略。我怀疑这些非局部效应是代码缺陷的最重要来源之一。ATL很聪明,优化了一个增量和一个递减(编译器很可能可以自己优化出来),但作为回报,你得到了一盒”火柴盒”。

(我并不是要在这里挑剔ATL,它试图设计的又小又快,但代价是增加了复杂性,并且这种复杂性是很微妙的,难以一眼就能理解的)

总结

使用引用计数来管理对象的生命周期,我一直是比较抗拒的。我总是担心会发生一些令人意想不到的事情(比如发生了地震导致CPU上的一根引脚短路),导致了本该释放的对象因为引用计数的计算错误而没有得到释放,或者本不该释放的对象,因为引用计数而提前释放。
我不能将一个随时可能崩溃的程序交付给我的用户,绝不。
如果正在阅读本文的大大(你)有什么好的妙招,希望能对愚钝的我指教一二。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《On objects with a reference count of zero》

当对象的引用计数为零时

 文章来源地址https://www.toymoban.com/news/detail-418472.html

到了这里,关于当对象的引用计数为零时的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RCU安全引用计数

    原文网址:https://lwn.net/Articles/93617 原文作者:Corbet 原文时间:2004年7月14日 内核提供了一种用于实现引用计数的简单机制kref;该机制是今年3月份完成的。kref机制的核心思想是,提供支持原子操作的计数器,用于对未决引用【outstanding references】进行计数。如果计数器数值为

    2024年02月11日
    浏览(42)
  • C++引用计数

    引用计数(reference count)的核心思想是使用一个计数器来标识当前指针指向的对象被多少类的对象所使用(即记录指针指向对象被引用的次数)。它允许有多个相同值的对象共享这个值的实现。引用计数的使用常有两个目的: 简化跟踪堆中(也即C++中new出来的)的对象的过程

    2024年02月11日
    浏览(34)
  • iOS——引用计数(一)

    自动引用计数(ARC,Automatic Reference Counting)是指内存管理中对引用采取自动计数的技术。 满足以下要求后,我们的代码就无需再次键入retain或者是release代码了: 使用Xcode 4.2或以上版本 使用LLVM编译器3.0或以上版本 编译器选项中设置ARC为有效 在以上条件下编译源代码时,编

    2024年02月07日
    浏览(43)
  • C++智能指针学习——小谈引用计数

    目录 前言 控制块简介 共享控制块 引用计数与弱引用计数创建过程 __shared_ptr __shared_count _Sp_counted_base 弱引用计数增加过程 再谈共享控制块 __weak_count 引用计数增加过程 弱引用计数的减少过程 弱引用计数减为0 引用计数的减少过程 引用计数减为0 参考文章 本文结合源码讨论

    2024年04月08日
    浏览(48)
  • Java虚拟机(JVM):引用计数算法

    我们学习了Java内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来就已知的,因此这几个区域

    2024年02月12日
    浏览(42)
  • 避免创建不必要的对象

    1、一般来说,最好能重用对象而不是每次需要的时候就创建一个功能相同的新对象 先看一个反例,如下所示: 该语句每次被执行都会创建一个新的String实例。传递给String构造器的参数 \\\"No way\\\" 本身就是一个String实例,功能方面等同于构造器创建的对象。如果被频繁调用,会创

    2024年02月07日
    浏览(37)
  • 【C语言】-- 一篇带你了解指针,内存,解引用

    目录 1、什么是指针? 1.1 内存 1.2 指针变量 二、指针和指针类型 1、指针类型 2、指针+整数 3、指针的解引用 三、野指针 1、野指针成因 (1) 指针未初始化 (2) 指针越界访问 (3) 指针指向的空间释放 2、如何规避野指针 四、指针运算 1、指针-指针        本篇文章我们来了解C语

    2024年02月16日
    浏览(58)
  • 49天精通Java,第34天,finalize、引用计数、JVM停止复制、JVM即时编译器

    在Java中,finalize()是一个Object类的方法,用于在对象被垃圾收集器回收之前执行一些清理操作。当一个对象成为垃圾时,它的finalize()方法会被自动调用。 finalize()方法的语法格式如下:

    2024年02月07日
    浏览(48)
  • 【C++系列P2】引用——背刺指针的神秘刺客(精讲一篇过!)

    前言 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎! 如标题所示,本章主要内容主要来侃侃“ 引用 ”这个刺客!如下就是大纲啦~ 引用,即 取别名 。它的最大特点是编译器 不会为引用变量而开辟空间 ,他们 共用同一块 空间。   1. 引用使用时必须要 初始化 。 2. 引用在初

    2024年02月10日
    浏览(68)
  • 一篇关于计算机网络原理的文章

    计算机网络原理是指计算机网络的基本概念、协议以及通信技术等方面的知识。 了解计算机网络原理对于我们使用互联网、编程开发以及网络安全等方面都极为重要。 在本文中,将介绍计算机网络原理的基本内容。 一、计算机网络的基本概念 计算机网络是指将分布在不同地

    2023年04月23日
    浏览(93)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包