设为首页 加入收藏

TOP

1.5 原始指针有何不妥(1)
2013-10-07 16:00:54 来源: 作者: 【 】 浏览:78
Tags:1.5 原始 指针 不妥

1.5 原始指针有何不妥(1)

指向对象的原始指针(raw pointer)是坏的,尤其当暴露给别的线程时。Observable应当保存的不是原始的Observer*,而是别的什么东西,能分辨Observer 对象是否存活。类似地,如果Observer 要在析构函数里解注册(这虽然不能解决前面提到的race condition,但是在析构函数里打扫战场还是应该的),那么subject_ 的类型也不能是原始的Observable*。

有经验的C++(www.cppentry.com) 程序员或许会想到用智能指针。没错,这是正道,但也没那么简单,有些关窍需要注意。这两处直接使用shared_ptr 是不行的,会形成循环引用,直接造成资源泄漏。别着急,后文会一一讲到。

空悬指针

有两个指针p1 和p2,指向堆上的同一个对象Object,p1 和p2 位于不同的线程中(图1-1 的左图)。假设线程A 通过p1 指针将对象销毁了(尽管把p1 置为了NULL),那p2 就成了空悬指针(图1-1 的右图)。这是一种典型的C/C++(www.cppentry.com) 内存错误。

 
图1-1

要想安全地销毁对象,最好在别人(线程)都看不到的情况下,偷偷地做。(这正是垃圾回收的原理,所有人都用不到的东西一定是垃圾。)

一个“解决办法”

一个解决空悬指针的办法是,引入一层间接性,让p1 和p2 所指的对象永久有效。比如图1-2 中的proxy 对象,这个对象,持有一个指向Object 的指针。(从C语言的角度,p1 和p2 都是二级指针。)

 
(点击查看大图)图1-2
当销毁Object 之后,proxy 对象继续存在,其值变为0(见图1-3)。而p2 也没有变成空悬指针,它可以通过查看proxy 的内容来判断Object 是否还活着。
 
图1-3

要线程安全地释放Object 也不是那么容易,race condition 依旧存在。比如p2看第一眼的时候proxy 不是零,正准备去调用Object 的成员函数,期间对象已经被p1 给销毁了。

问题在于,何时释放proxy 指针呢?

一个更好的解决办法

为了安全地释放proxy,我们可以引入引用计数(reference counting),再把p1和p2 都从指针变成对象sp1 和sp2。proxy 现在有两个成员,指针和计数器。

1. 一开始,有两个引用,计数值为2(见图1-4)。

 
图1-4

2. sp1 析构了,引用计数的值减为1(见图1-5)。
 
图1-5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇1.4 线程安全的Observer 有多难 下一篇1.5 原始指针有何不妥(2)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·MySQL 安装及连接-腾 (2025-12-25 06:20:28)
·MySQL的下载、安装、 (2025-12-25 06:20:26)
·MySQL 中文网:探索 (2025-12-25 06:20:23)
·Shell脚本:Linux Sh (2025-12-25 05:50:11)
·VMware虚拟机安装Lin (2025-12-25 05:50:08)