银色月光下

漫漫长夜

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  4 Posts :: 7 Stories :: 0 Comments :: 0 Trackbacks

常用链接

留言簿(12)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜


对象生命周期是个很大的课题 ,本文仅是♂科普贴,介绍了对象生命周期管理的概念,原理,方法,并给出相关链接。

对象

在程序事务中,涉及使用各种资源(内存,IO句柄,GDI等),在面向对象方法学里,我们将资源包装成对象,对象的 构造/销毁,对应资源的申请/释放

生命周期

我们不能一直创建对象(资源泄露),也不能在资源销毁后,继续访问(野指针效句柄),我们需要在合适的时机释放合适的对象。


对象生命周期管理分三类,

  • 手动管理
  • 半自动管理 —— 编译器检查,通过库实现的智能指针等
  • 全自动管理 —— GC

一些例子:

  • C语言提供最基础的资源管理模型,

    • 内存分配释放,malloc, free,

    • 文件句柄分配释放

        File* f = openFile()   ...   closeFile(f) 

      习惯上,我们通过提供API,帮助用户在模块级别上进行管理

        module_hanler* h = module_init(...);   h.operator(...)   module_release(h) 

      手动管理麻烦,容易出错,调试复杂,但操作系统级别的开发,不可缺少。

  • c++的对象语义提供了RAII

    • 通过构造函数,析构函数,能够完成作用域的自动化管理,

      //CFile.h class CFile{     File* fh = NULL; public:     CFile(char* path)     {         fh = openFile(path);         ...     }     ~CFile()     {         closeFile();     } }  //testFile.cpp void testFile() {     CFile f("xxx.txt");     f.print(); }//这里自动释放 
    • c# 提供了 Dispose接口 和 using关键字,离开作用域的对象立即回收

    RAII,一定程度上,减轻了程序员管理内存的负担,但它无法帮助解决,对象被引用,对象传递到作用域外的问题。

  • (编译器自动管理)智能指针

    • 作用域 [[1]] [top]:c++/rust里的 {...}, 定义了对象作用域,c#的 using(...){...}, 定义了作用域

    • 裸指针:离开作用域,不会自动销毁,需要主动调用 delete obj_ptr;

    • 智能指针:

      通过编译器的魔法,我们创造出智能指针(smart_ptr),既保留了作用域的安全性,也保留了指针灵活性 智能指针设计到以下的概念,

      • 所有权转移: 当发生指针赋值的情况,原指针失效,如果再次使用,引发编译时错误(rust),运行时错误(c++) 对应c++的unique_ptr,和rust的Box<>

      • 引用计数 一个指针被多个对象引用,当所有对象都不再持有,对象自动销毁,引用计数有时被看作是一种即时回收的GC,

      • 弱引用 引用计数有一个问题,它解决不了在循环引用的情况,这样整个引用链里的所有对象都不能正确回收,弱引用,可以将循环链在合适的地方断掉。 另外需要留意的是,在完整GC的语言里,弱引用也是一种常用的内存管理技术[1]

        c++提供了, uniq_ptr, shart_ptr, weak_ptr, 对应以上的概念,但还面临线程安全问题

        rust 提供了更多的智能指针类型,和检查机制,能够处理包括,所有权转移后不可再用, 线程资源安全在内的问题

  • 垃圾回收

    垃圾回收来自于这样的想法,程序员不应该关心对象如何回收,运行时自己去解决。

    原理: 已创建对象 - 环境栈上的对象 - 所有可到达对象 == 垃圾对象

    标记-清除 算法:

    1. 所有对象初始标记 不可回收
    2. 资源使用到达阈值-> 翻转不可回收标记为可回收标记,
    3. 栈对象加入可访问对象集,
    4. 个可访问对象的引用成员,加入可访问对象集,并标记不可回收,递归至所有可访问对象上色,
    5. 遍历全部对象,回收所有未染色对象

    实际的垃圾回收算法极其复杂,至今,没有一个完美的并发算法,使得在GC时,系统不暂停(stop the world)

  • 其它

    • 对象池 对象池 省去对象反复创建,销毁的成本

    通常 对象需要提供,无参的 构造函数,init(...), reset()规范,对象池通过栈实现.

      template<typename OBJECT>   class object_pool   {       OBJECT* create_object(...)       {           auto object = pool.pop()           object.init(...)           ...       }              void release_object(OBJECT object)       {           object.reset()           pool.push(object)       }       ...   }        
    • 整页分配

      对于一次事务,分配足够内存(或是动态增长), 对象只创建,无需回收,事务完成,整页回收,这样的好处是分配极快,但需要清楚事务的边界,不可跨事务使用。

posted on 2016-07-05 12:18 lichking 阅读(361) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理