Skip to content

Latest commit

 

History

History
32 lines (29 loc) · 4.23 KB

memory.md

File metadata and controls

32 lines (29 loc) · 4.23 KB

OSG内存管理

连锁释放

  • OSG 提供了一种自动的“废弃物”收集系统,它使用一种名为内存引用计数器(referencecounted memory)的方式工作。所有的 OSG 场景图形节点均采用引用计数(reference count)的方式,当引用计数值减为 0 时,此对象将被自动释放。

连锁释放依赖的组件

  • OSG 的“废弃物”收集系统有以下两个组件:
    • 通用的基类 osg::Referenced, 所有的 OSG 节点和场景图形均继承自这一基类,它包含了一个整型的引用计数器。
    • OSG 定义的智能指针模板类 ref_ptr<>。当代码中一个 Referenced 对象指针赋予类型变量 ref_ptr<>时, Referenced 类的引用计数器会自动加 1。
  • 如果程序要保存一个继承自Referenced的对象的指针,那么将指针保存在ref_ptr< >中要好过使用标准 C++指针变量。如果代码中可以始终遵循这一原则,那么当最后一个引用对象的ref_ptr< >被弃用时,对象所占用的内存将自动释放。当你创建任何继承自 Referenced 的场景图形节点或数据时, 你的应用程序不可以直接释放其内存空间。除了极少数例外,几乎所有的Referenced派生类都声明了保护析构函数。这样可以保证,继承自Referenced的对象只能够通过减少引用计数器到 0 的方式来释放其内存。

相关类

  • Referenced
    • Referenced 类(命名空间:osg)实现了对内存区段的引用计数器功能。所有的 OSG 节点和场景图形数据,包括状态信息,顶点数组,法线,以及纹理坐标,均派生自 Referenced 类。因此,所有的 OSG 场景图形均可以进行内存引用计数。
    • Referenced 类包括了三个主要组成部分:
      • 保护成员整型变量_refCount,用作引用计数,在构造时被初始化为 0。
      • 公有函数 ref()unref(),用于实现_refCount 值的增加和减少。当_refCount 为 0 时, unref()将自动释放该对象所占用的内存。
      • 作为保护成员存在的虚析构函数。堆栈的创建和显示的析构均会因为析构函数受保护而被禁止,而虚函数的特性将允许用户执行子类的析构函数。
    • 总体上来说,用户的代码基本上不需要直接调用 ref()unref()函数,只要使用ref_ptr<>进行处理即可。
  • ret_ptr< >模板类
    • ref_ptr<>(命名空间: osg)用于实现一个指向Referenced 对象的智能指针,并对其引用计数器进行管理。当最后一个引用 Referenced 对象的 ref_ptr<>失去作用时,对象将确保被释放。
    • ref_ptr<>简化了场景图形内存释放的工作,并保证当错误的调用堆栈展开时,对象也可以被正确释放。
    • ref_ptr<>模板类包括以下三个主要的组成部分:
      • 一个私有指针_ptr,用于保存管理内存区域的地址。可以用 get()方法返回_ptr 的值。
      • 为了使 ref_ptr< >可以像正常的 C++指针一样工作, 重载或定义了一些方法,如 operator->()operator=()
      • valid()方法用于判断 ref_ptr<>是否为空,不为 NULL 时返回 TRUE。当程序将一个地址指定给 ref_ptr<>变量时,ref_ptr<>的重载函数 operator=()将会假定此地址指向一个 Referenced 派生对象,并自动调用Referenced::ref(),将引用计数值自动加一。
    • ref_ptr< >变量的引用计数值减少的情形有这样两种:
      • ref_ptr< >被释放(在类的析构函数里执行减一),或者重新进行了赋值(在 operator=()里执行减一)。在以上两种情况中, ref_ptr< >都会通过调用 Referenced::unref()来执行减少引用计数值的操作。

总结

  • 将派生自 Referenced 的对象赋予 ref_ptr< >变量,这一动作将自动调用Referenced::ref()并使引用计数加一。
    • 如果将ref_ptr< >变量指向其它的对象,或者将其释放,那么将调用Referenced::unref()方法,使引用计数减一。当计数器的值为0时,unref()自动释放对象所占用的内存空间。
    • 为新的 Referenced 对象开辟内存空间时,要尽量将其赋予ref_ptr< >,以保证 OSG 的内存管理工作正确。