原文:ogre内存管理

OGRE内存分配策略相关文件及简述

OGRE提供了自己的内存分配策略,甚至为STL容器提供了新的分配策略,相关文件及简述如下:

OgreMemoryAllocatedObject.h  OgreMemoryAllocatedObject.cpp

// 所有使用Ogre内存分配器的类的父类

OgreMemoryAllocatorConfig.h

// 配置内存分配相关规则

OgreMemoryNedAlloc.h  OgreMemoryNedAlloc.cpp

// 使用nedalloc库,定义了类NedAllocPolicy、NedAlignedAllocPolicy

OgreMemoryNedPooling.h  OgreMemoryNedPooling.cpp

// 使用nedalloc库,定义了类NedPoolingPolicy、NedPoolingAlignedPolicy

OgreMemoryStdAlloc.h

// 定义了类StdAllocPolicy、StdAlignedAllocPolicy

// 只是对malloc/free的简单包装

OgreMemorySTLAllocator.h

// 为STL容器提供的分配器

OgreMemoryTracker.h  OgreMemoryTracker.cpp

// 用于跟踪内存的分配和释放,并统计内存的使用和泄漏情况

// *为避免循环引用,OgreMemoryTracker.h头文件必须在OgrePrerequisites.h引用后引用*

OgreAlignedAllocator.h  OgreAlignedAllocator.cpp

// 提供对齐内存分配函数

对于OGRE中STL容器的内存分配策略的简述:

以下是摘自OgrePrerequisites.h的代码:

template <typename T, typename A = STLAllocator<T, GeneralAllocPolicy> >

struct vector

{

#if OGRE_CONTAINERS_USE_CUSTOM_MEMORY_ALLOCATOR

typedef typename std::vector<T, A> type;

#else

typedef typename std::vector<T> type;

#endif

};

如上所示,OGRE对STL容器进行了简单的包装,使其默认使用OGRE提供了内存分配策略GeneralAllocPolicy。在

OgreMemoryAllocatorConfig.h头文件中,能够容易找到GeneralAllocPolicy的定义。这样,在使用STL容器时须加“::type”,如Ogre::vector<T>::type,或者照旧使用STL本身的内存分配策略,如std::vector<T>。如需要改变STL容器使用的内存策略,则可以按如下方式使用,Ogre::vector<T,STLAllocator<T,CustomPolicy>>::type,其中CustomPolicy为用户指定的内存策略。

OGRE的内存策略配置及如何自定义内存策略

OGRE的内存策略配置

OGRE中默认所有类型使用一致的内存分配策略,并在编译时便决定。在OgreMemoryAllocatorConfig.h文件中由OGRE_MEMORY_ALLOCATOR宏选择相应的内存策略。

OGRE提供了如下三种内存策略:

NedAllocPolicy(NedAlignedAllocPolicy)

NedPoolingPolicy(NedPoolingAlignedPolicy)

StdAllocPolicy(StdAlignedAllocPolicy)

在OgreConfig.h中定义有

#define OGRE_MEMORY_ALLOCATOR_STD 1

#define OGRE_MEMORY_ALLOCATOR_NED 2

#define OGRE_MEMORY_ALLOCATOR_NEDPOOLING 4

在OgreBuildSettings.h中定义有

#define OGRE_MEMORY_ALLOCATOR 4

即OGRE默认使用的内存分配策略为NedPoolingPolicy。

*** OgreMemoryAllocatorConfig.h文件中定义MemoryCategory枚举类型,以支持不同目的使用不同的内存分配方式,但需用户自己实现。

如何自定义内存分配策略

(假定类名为CustomAllocPolicy,对齐类为CustomAlignAllocPolicy):

1. 在CustomAllocPolicy和CustomAlignAllocPolicy中至少实现如下三个静态函数:

//分配内存

static inline void* allocateBytes(size_t count, const char* file = 0, int line = 0, const char* func = 0);

//释放内存

static inline void deallocateBytes(void* ptr);

//获取一次性分配的最大分配数量

static inline size_t getMaxAllocationSize();

2. 在OgreConfig.h头文件中添加相应宏定义

如  #define OGRE_MEMORY_ALLOCATOR_CUSTOM 5

3. 在OgreMemoryAllocatorConfig.h头文件中添加代码行,如

#elif OGRE_MEMORY_ALLOCATOR == OGRE_MEMORY_ALLOCATOR_CUSTOM

# include "OgreMemoryCustomAlloc.h"  //CustomAllocPolicy类所在头文件

namespace Ogre

{

template <MemoryCategory Cat> class CategorisedAllocPolicy : public CustomAllocPolicy{};

template <MemoryCategory Cat, size_t align = 0> class CategorisedAlignAllocPolicy : public CustomAlignAllocPolicy<align>{};

}

4. 最后在OgreBuildSettings.h中改变定义

#define OGRE_MEMORY_ALLOCATOR 

如何在程序中使用OGRE提供的内存策略

要使用OGRE提供的内存策略(或自定义的内存策略)主要有两种方式:

1. 继承AllocatedObject类

2. 使用OgreMemoryAllocatorConfig.h头文件中定义的内存操作宏

继承AllocatedObject类

AllocatedObject类中重载了new、new[]、delete及delete[]等操作符,所以若要A类使用Ogre提供的或自定义的内存策略,只需继承AllocatedObject类即可。AllocatedObject类以模板的形式支持各种内存分配策略。在OgreMemoryAllocatorConfig.h头文件中对各种模板的AllocatedObject类进行了“重命名”,例如:

typedef CategorisedAllocPolicy<Ogre::MEMCATEGORY_GENERAL> GeneralAllocPolicy;

typedef AllocatedObject<GeneralAllocPolicy> GeneralAllocatedObject;

typedef GeneralAllocatedObject  ArchiveAlloc;

typedef GeneralAllocatedObject  ConfigAlloc;

所以在继承使用AllocatedObject类时,可考虑使用OgreMemoryAllocatorConfig.h头文件中的宏定义。例如:

(举例多取自OGRE源码,一般都标注了其文件名)

class _OgreExport ConfigFile : public ConfigAlloc //OgreConfigFile.h

class _OgreExport ArchiveManager : public Singleton<ArchiveManager>, public ArchiveAlloc  // OgreArchiveManager.h

而为了统一形式,在OgreMemoryAllocatorConfig.h头文件中为继承自AllocatedObject的类定义如下两个宏:

#define OGRE_NEW new

#define OGRE_DELETE delete

因此在使用时,形式如下

ArchiveManager* mArchiveManager = OGRE_NEW ArchiveManager();

使用内存操作宏

除了继承使用AllocatedObject类之外,对于C++中的原始类型(int, double等),或者来自外部库的不能更改的类型,或者某些原因而不能继承AllocatedObject的类型来说,如果要对它们使用Ogre自定义内存策略,则可以使用OgreMemoryAllocatorConfig.h头文件中定义的内存操作宏:

以下三个宏用于分配原始内存,只是分配相应大小的内存,并不进行初始化:

OGRE_MALLOC(bytes, category)

-- 分配bytes大小的内存

OGRE_ALLOC_T(T, count, category)

-- 分配sizeof(T) * count大小的内存

OGRE_FREE(ptr, category)

-- 与上述两个配对使用,释放ptr指向的内存

以下四个宏分配相应内存并进行初始化:

OGRE_NEW_T(T, category)

-- 分配sizeof(T)大小的内存,并调用T的构造函数

OGRE_NEW_ARRAY_T(T, count, category)

-- 分配sizeof(T) * count大小的内存,并对count个T类型实例依次初始化

OGRE_DELETE_T(ptr, T, category)

– 与OGRE_NEW_T 配对使用,调用T的析构函数,释放相应内存

OGRE_DELETE_ARRAY_T(ptr, T, count, category)

--与OGRE_NEW_ARRAY_T配对使用,对count个T类型实例依次调用其析构函数,释放相应内存

举例:

// OgreTexture.cpp

void* pixData = OGRE_MALLOC(dataSize, Ogre::MEMCATEGORY_GENERAL);

// OgreAxisAlignedBox.h

Vector3* mpCorners = OGRE_ALLOC_T(Vector3, 8, MEMCATEGORY_SCENE_CONTROL);

OGRE_FREE(mpCorners, MEMCATEGORY_SCENE_CONTROL);

// OgreAnimationState.cpp

BoneBlendMask* mBlendMask = OGRE_NEW_T(BoneBlendMask, MEMCATEGORY_ANIMATION)(blendMaskSizeHint);

OGRE_DELETE_T(mBlendMask, BoneBlendMask, MEMCATEGORY_ANIMATION);

// OgreBspLevel.cpp

Brush * mBrushes = OGRE_NEW_ARRAY_T(BspNode::Brush, mNumBrushes, MEMCATEGORY_GEOMETRY);

OGRE_DELETE_ARRAY_T(mBrushes, Brush, (size_t)mNumBrushes, MEMCATEGORY_GEOMETRY);

对于以上7个内存操作宏分别有与其对应的对齐方式的宏定义,如OGRE_MALLOC_SIMD、OGRE_MALLOC_ALIGN、OGRE_ALLOC_T_SIMD、OGRE_NEW_T_ALIGN、OGRE_DELETE_ARRAY_T_ALIGN 等等。

***使用这些宏时,如果类型T本身继承于AllocatedObject,对程序本身也不会产生什么坏的影响,除了显得多此一举。

Ogre提供的内存分配/释放跟踪器

在Ogre自己提供的NedAllocPolicy(NedAlignedAllocPolicy)、NedPoolingPolicy(NedPoolingAlignedPolicy)、StdAllocPolicy(StdAlignedAllocPolicy)三种内存分配策略中,都包含了分配/释放跟踪功能,如需在自定义的分配策略中添加跟踪功能,照搬即可。该功能由MemoryTracker类实现,它统计内存的分配和释放情况,以及内存分配语句所在文件名、行号和函数名。默认在程序结束时将统计信息输出到终端,并保存于OgreLeaks.log文件,也可通过成员函数setReportToStdOut(bool rep)和setReportFileName(const std::string& name)设置输出方式。

跟踪器的使用方式都在分配策略中完成,无需在它处额外操作。唯一需要设置的就是跟踪器开关的打开与关闭

在OgrePrerequisites.h文件中有如下宏定义

#if OGRE_DEBUG_MODE

#if OGRE_MEMORY_TRACKER_DEBUG_MODE

#define OGRE_MEMORY_TRACKER 1

#else

#define OGRE_MEMORY_TRACKER 0

#endif

#else

#if OGRE_MEMORY_TRACKER_RELEASE_MODE

#define OGRE_MEMORY_TRACKER 1

#else

#define OGRE_MEMORY_TRACKER 0

#endif

#endif

即,OGRE_MEMORY_TRACKER宏开关取决于OGRE_MEMORY_TRACKER_DEBUG_MODE 或OGRE_MEMORY_TRACKER_RELEASE_MODE。而在OgreBuildSettings.h中定义有

#define OGRE_MEMORY_TRACKER_DEBUG_MODE 0

#define OGRE_MEMORY_TRACKER_RELEASE_MODE 0

即默认是关闭跟踪器的,如果需要在DEBUG版下打开跟踪器,只需要将OGRE_MEMORY_TRACKER_DEBUG_MODE设置为1。而根据OgreMemoryAllocatorConfig.h文件中内存操作宏的设置():

#if OGRE_DEBUG_MODE    //语句1

…//详见源文件

#else // !OGRE_DEBUG_MODE

#endif // OGRE_DEBUG_MODE

即便是打开了OGRE_MEMORY_TRACKER_RELEASE_MODE宏,跟踪器也不能记录内存分配语句所在文件名、行号和函数名,即不能正常工作。如果需要在Release版下正常开启跟踪器功能,建议将语句1“#if OGRE_DEBUG_MODE”改为“#if OGRE_MEMORY_TRACKER”。

举例:

对于如下代码

#include <string>

#include <OgreRoot.h>

#include <OgreMemoryAllocatorConfig.h>

#include <OgreArchiveManager.h>

using std::string;

int main()

{

{

int *pi = OGRE_NEW_T(int, Ogre::MEMCATEGORY_GENERAL)(50);

OGRE_FREE(pi, Ogre::MEMCATEGORY_GENERAL); //释放

double *pd = OGRE_NEW_ARRAY_T(double, 5, Ogre::MEMCATEGORY_GENERAL);

OGRE_FREE(pd, Ogre::MEMCATEGORY_GENERAL); //释放

string *ps =  OGRE_NEW_T(string, Ogre::MEMCATEGORY_GENERAL)("hello");

OGRE_DELETE_T(ps, string, Ogre::MEMCATEGORY_GENERAL); //释放

}

{

Ogre::ArchiveManager* mArchiveManager = OGRE_NEW Ogre::ArchiveManager();

OGRE_DELETE mArchiveManager; //释放

}

return 0;

}

现开启跟踪器宏开关,即将OGRE_MEMORY_TRACKER_DEBUG_MODE 和 OGRE_MEMORY_TRACKER_RELEASE_MODE 都置为1(须重新编译)。该代码正确释放了所有内存,不存在内存泄漏。如果将代码中释放内存的语句全部注释掉,则在Debug版下生成的OgreLeaks.log文件的内容为:

Ogre Memory: Detected memory leaks !!!

Ogre Memory: (6) Allocation(s) with total 244 bytes.

Ogre Memory: Dumping allocations ->

e:\vs project\ogretest\testmain.cpp(12) : {4 bytes} function: main

e:\vs project\ogretest\testmain.cpp(15) : {40 bytes} function: main

e:\vs project\ogretest\testmain.cpp(25) : {64 bytes} function: main

(unknown source):(0) : {52 bytes} function:

(unknown source):(0) : {52 bytes} function:

e:\vs project\ogretest\testmain.cpp(18) : {32 bytes} function: main

在Release版下生成的OgreLeaks.log文件的内容为:

Ogre Memory: Detected memory leaks !!!

Ogre Memory: (8) Allocation(s) with total 248 bytes.

Ogre Memory: Dumping allocations ->

(unknown source):(0) : {48 bytes} function:

(unknown source):(0) : {28 bytes} function:

(unknown source):(0) : {4 bytes} function:

(unknown source):(0) : {4 bytes} function:

(unknown source):(0) : {4 bytes} function:

(unknown source):(0) : {72 bytes} function:

(unknown source):(0) : {40 bytes} function:

(unknown source):(0) : {48 bytes} function:

可以看出在Debug版下,跟踪器正常工作,顺利的检测出全部四处内存泄漏,而在Release版下则不能正常工作。将“#if OGRE_DEBUG_MODE”改为“#if OGRE_MEMORY_TRACKER”后,重新在Release版下测试,跟踪器便能正常工作,生成的OgreLeaks.log的内容为:

Ogre Memory: Detected memory leaks !!!

Ogre Memory: (8) Allocation(s) with total 248 bytes.

Ogre Memory: Dumping allocations ->

(unknown source):(0) : {48 bytes} function:

.\TestMain.cpp(18) : {28 bytes} function: main

.\TestMain.cpp(12) : {4 bytes} function: main

(unknown source):(0) : {4 bytes} function:

(unknown source):(0) : {4 bytes} function:

.\TestMain.cpp(25) : {72 bytes} function: main

.\TestMain.cpp(15) : {40 bytes} function: main

(unknown source):(0) : {48 bytes} function:

P.S.

1. 测试代码中,对int和double类型使用的是OGRE_NEW_T 和 OGRE_FREE 来分别分配和释放内存,而并非前文所说的OGRE_DELETE_T,原因是因为对于int,double等基本类型来说,是没有析构函数的,而OGRE_DELETE_T宏是要调用相应析构函数的。

2. 测试代码中,若将using std::string;注释掉,并将相应string类型测试语句换为如下两句:

std::string *ps2 = OGRE_NEW_T(std::string, Ogre::MEMCATEGORY_GENERAL)("world");

OGRE_DELETE_T(ps2, basic_string, Ogre::MEMCATEGORY_GENERAL);

其中basic_string 不能是string 或 std::string !!!  同样是因为OGRE_DELETE_T宏要调用basic_string类的析构函数。类似情况还有在使用std::fostream,std::fistream等等时。

 
 

【转载】ogre内存管理的更多相关文章

  1. 【转载】OGRE 内存管理

    原文:OGRE 内存管理 Ogre引擎中与内存管理相关的文件大致有以下几个(只列出头文件) OgreAlignedAllocator.h OgreMemoryAllocatedObject.h Ogr ...

  2. [转载]C++内存管理

    [导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不 ...

  3. [转载] Linux内存管理之mmap详解

    转载自http://blog.chinaunix.net/uid-26669729-id-3077015.html 一. mmap系统调用 1. mmap系统调用 mmap将一个文件或者其它对象映射进 ...

  4. 转:内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]

    内存区划分.内存分配.常量存储区.堆.栈.自由存储区.全局区[C++][内存管理][转载] 一. 在c中分为这几个存储区1.栈 - 由编译器自动分配释放2.堆 - 一般由程序员分配释放,若程序员不释放 ...

  5. Apache Spark 内存管理详解(转载)

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...

  6. iOS 内存管理(转载)

     N久没维护这个博客了,从开始接触编程到现在已经三四年了.不太习惯写博客,这应该是个不好的习惯.所以从哪哪天开始,我得改变自己 (:       . 文采不太好,因此很多的文章都会借鉴他人的,但是我一 ...

  7. 【转载】浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多? 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在 ...

  8. [转载]Java应用程序中的内存泄漏及内存管理

    近期发现测试的项目中有JAVA内存泄露的现象.虽然JAVA有垃圾回收的机制,但是如果不及时释放引用就会发生内存泄露现象.在实际工作中我们使用Jprofiler调用java自带的 jmap来做检测还是很 ...

  9. <转载>内存管理内幕-动态分配的选择、折衷和实现 对malloc内存分配有个简单的描述,对内存管理有个大致的说明

    这篇文章看后感觉不错,和我在glibc下的hurdmalloc.c文件里关于malloc的实现基本意思相同,同时,这篇文章还介绍了一些内存管理方面的知识,值得推荐. 原文链接地址为:http://ww ...

随机推荐

  1. some software that is used to speed up your system

    1.RAMDISK take some space in ram and use them as the disk. Primo Ramdisk Server Edition 5.6.0 regist ...

  2. LR 常见问题收集及总结

    一:LoadRunner常见问题整理 1.LR 脚本为空的解决方法: 1.去掉ie设置中的第三方支持取消掉 2.在系统属性-高级-性能-数据执行保护中,添加loadrunner安装目录中的vugen. ...

  3. 两个升序链表的合并 Merge Two Sorted Lists 【 leetcode】

    class Solution {public:   ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {   ListNode *p; ListN ...

  4. webconfig简单加密解密

    <?xml version="1.0"?><configuration> <configSections> <section name=& ...

  5. 使用repeater实现gridview的功能

    <asp:Repeater ID="rptfindData" runat="server"> <HeaderTemplate> < ...

  6. python中字符串\r的奇怪问题

    示例: 我这里有一字符串: u'北京市工商行政管理局大兴分局\r <a onclick="showJDS(\'fa641bb3be5b44a1b618433833982fee\',\' ...

  7. WAMP,BITNAMI上建立多个虚拟主机都访问到主站上去了怎么解决?

    新建立了多个虚拟主机,访问的结果都是localhost,只要把localhost也建立成一个虚拟主机所有的虚拟主机访问就正常了.

  8. cmake用法(转)

    转自:http://blog.csdn.net/dbzhang800/article/details/6314073 新工作中使用到了cmake,所以找点资料学习一下,这篇讲的确实不错,转过来保存一下 ...

  9. 什么是RAW数据?

    现在数码照片的存储格式,以及在网络上应用的最普遍的图片格式就是JPEG格式了(Joint Photographic Expert Group).但是作为一种有损的图像压缩格式(现在也有少数数码相机提供 ...

  10. Combox控件初始化项的技巧

    有时候combox下拉项就是几条固定的,不需要做数据绑定,但是如果直接采用字符串集合编辑器的时候,SelectedValue貌似会不起作用. 于是简单的封装一下 /// <summary> ...