【转载】ogre内存管理
原文:ogre內(nèi)存管理
OGRE內(nèi)存分配策略相關(guān)文件及簡述
?
OGRE提供了自己的內(nèi)存分配策略,甚至為STL容器提供了新的分配策略,相關(guān)文件及簡述如下:
OgreMemoryAllocatedObject.h? OgreMemoryAllocatedObject.cpp
// 所有使用Ogre內(nèi)存分配器的類的父類
?
OgreMemoryAllocatorConfig.h
//?配置內(nèi)存分配相關(guān)規(guī)則
?
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
//?用于跟蹤內(nèi)存的分配和釋放,并統(tǒng)計(jì)內(nèi)存的使用和泄漏情況
//?*為避免循環(huán)引用,OgreMemoryTracker.h頭文件必須在OgrePrerequisites.h引用后引用*
?
OgreAlignedAllocator.h? OgreAlignedAllocator.cpp
//?提供對齊內(nèi)存分配函數(shù)
?
對于OGRE中STL容器的內(nèi)存分配策略的簡述:
?
以下是摘自O(shè)grePrerequisites.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容器進(jìn)行了簡單的包裝,使其默認(rèn)使用OGRE提供了內(nèi)存分配策略GeneralAllocPolicy。在
OgreMemoryAllocatorConfig.h頭文件中,能夠容易找到GeneralAllocPolicy的定義。這樣,在使用STL容器時須加“::type”,如Ogre::vector<T>::type,或者照舊使用STL本身的內(nèi)存分配策略,如std::vector<T>。如需要改變STL容器使用的內(nèi)存策略,則可以按如下方式使用,Ogre::vector<T,STLAllocator<T,CustomPolicy>>::type,其中CustomPolicy為用戶指定的內(nèi)存策略。
?
?
?
| OGRE的內(nèi)存策略配置及如何自定義內(nèi)存策略 ? OGRE的內(nèi)存策略配置 OGRE中默認(rèn)所有類型使用一致的內(nèi)存分配策略,并在編譯時便決定。在OgreMemoryAllocatorConfig.h文件中由OGRE_MEMORY_ALLOCATOR宏選擇相應(yīng)的內(nèi)存策略。 ? OGRE提供了如下三種內(nèi)存策略: ??? 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默認(rèn)使用的內(nèi)存分配策略為NedPoolingPolicy。 ***?OgreMemoryAllocatorConfig.h文件中定義MemoryCategory枚舉類型,以支持不同目的使用不同的內(nèi)存分配方式,但需用戶自己實(shí)現(xiàn)。 ? ? 如何自定義內(nèi)存分配策略 (假定類名為CustomAllocPolicy,對齊類為CustomAlignAllocPolicy): 1.?在CustomAllocPolicy和CustomAlignAllocPolicy中至少實(shí)現(xiàn)如下三個靜態(tài)函數(shù): //分配內(nèi)存 static inline void* allocateBytes(size_t count, const char* file = 0, int line = 0, const char* func = 0); //釋放內(nèi)存 static inline void deallocateBytes(void* ptr); //獲取一次性分配的最大分配數(shù)量 static inline size_t getMaxAllocationSize(); 2.?在OgreConfig.h頭文件中添加相應(yīng)宏定義 如??#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?5? |
?
?
?
如何在程序中使用OGRE提供的內(nèi)存策略
要使用OGRE提供的內(nèi)存策略(或自定義的內(nèi)存策略)主要有兩種方式:
1.?繼承AllocatedObject類
2.?使用OgreMemoryAllocatorConfig.h頭文件中定義的內(nèi)存操作宏
?
?
繼承AllocatedObject類
AllocatedObject類中重載了new、new[]、delete及delete[]等操作符,所以若要A類使用Ogre提供的或自定義的內(nèi)存策略,只需繼承AllocatedObject類即可。AllocatedObject類以模板的形式支持各種內(nèi)存分配策略。在OgreMemoryAllocatorConfig.h頭文件中對各種模板的AllocatedObject類進(jìn)行了“重命名”,例如:
typedef?CategorisedAllocPolicy<Ogre::MEMCATEGORY_GENERAL>?GeneralAllocPolicy;
typedef?AllocatedObject<GeneralAllocPolicy>?GeneralAllocatedObject;
typedef?GeneralAllocatedObject? ArchiveAlloc;
typedef?GeneralAllocatedObject??ConfigAlloc;
所以在繼承使用AllocatedObject類時,可考慮使用OgreMemoryAllocatorConfig.h頭文件中的宏定義。例如:
(舉例多取自O(shè)GRE源碼,一般都標(biāo)注了其文件名)
class?_OgreExport?ConfigFile?:?public?ConfigAlloc?//OgreConfigFile.h
class?_OgreExport?ArchiveManager?:?public?Singleton<ArchiveManager>,?public?ArchiveAlloc? //?OgreArchiveManager.h
而為了統(tǒng)一形式,在OgreMemoryAllocatorConfig.h頭文件中為繼承自AllocatedObject的類定義如下兩個宏:
#define?OGRE_NEW?new
#define?OGRE_DELETE?delete
因此在使用時,形式如下
ArchiveManager*?mArchiveManager?=?OGRE_NEW?ArchiveManager();
?
?
使用內(nèi)存操作宏
除了繼承使用AllocatedObject類之外,對于C++中的原始類型(int, double等),或者來自外部庫的不能更改的類型,或者某些原因而不能繼承AllocatedObject的類型來說,如果要對它們使用Ogre自定義內(nèi)存策略,則可以使用OgreMemoryAllocatorConfig.h頭文件中定義的內(nèi)存操作宏:
?
以下三個宏用于分配原始內(nèi)存,只是分配相應(yīng)大小的內(nèi)存,并不進(jìn)行初始化:
OGRE_MALLOC(bytes,?category)
???????-- 分配bytes大小的內(nèi)存
OGRE_ALLOC_T(T,?count,?category)
???????-- 分配sizeof(T) * count大小的內(nèi)存
OGRE_FREE(ptr,?category)
?????????-- 與上述兩個配對使用,釋放ptr指向的內(nèi)存
?
以下四個宏分配相應(yīng)內(nèi)存并進(jìn)行初始化:
OGRE_NEW_T(T,?category)
??????? -- 分配sizeof(T)大小的內(nèi)存,并調(diào)用T的構(gòu)造函數(shù)
OGRE_NEW_ARRAY_T(T,?count,?category)
????????-- 分配sizeof(T) * count大小的內(nèi)存,并對count個T類型實(shí)例依次初始化
OGRE_DELETE_T(ptr,?T,?category)
????????–?與OGRE_NEW_T?配對使用,調(diào)用T的析構(gòu)函數(shù),釋放相應(yīng)內(nèi)存
OGRE_DELETE_ARRAY_T(ptr,?T,?count,?category)
????????--與OGRE_NEW_ARRAY_T配對使用,對count個T類型實(shí)例依次調(diào)用其析構(gòu)函數(shù),釋放相應(yīng)內(nèi)存
?
舉例:
//?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個內(nèi)存操作宏分別有與其對應(yīng)的對齊方式的宏定義,如OGRE_MALLOC_SIMD、OGRE_MALLOC_ALIGN、OGRE_ALLOC_T_SIMD、OGRE_NEW_T_ALIGN、OGRE_DELETE_ARRAY_T_ALIGN?等等。
***使用這些宏時,如果類型T本身繼承于AllocatedObject,對程序本身也不會產(chǎn)生什么壞的影響,除了顯得多此一舉。
?
Ogre提供的內(nèi)存分配/釋放跟蹤器
在Ogre自己提供的NedAllocPolicy(NedAlignedAllocPolicy)、NedPoolingPolicy(NedPoolingAlignedPolicy)、StdAllocPolicy(StdAlignedAllocPolicy)三種內(nèi)存分配策略中,都包含了分配/釋放跟蹤功能,如需在自定義的分配策略中添加跟蹤功能,照搬即可。該功能由MemoryTracker類實(shí)現(xiàn),它統(tǒng)計(jì)內(nèi)存的分配和釋放情況,以及內(nèi)存分配語句所在文件名、行號和函數(shù)名。默認(rèn)在程序結(jié)束時將統(tǒng)計(jì)信息輸出到終端,并保存于OgreLeaks.log文件,也可通過成員函數(shù)setReportToStdOut(bool rep)和setReportFileName(const std::string& name)設(shè)置輸出方式。
跟蹤器的使用方式都在分配策略中完成,無需在它處額外操作。唯一需要設(shè)置的就是跟蹤器開關(guān)的打開與關(guān)閉
在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宏開關(guān)取決于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
即默認(rèn)是關(guān)閉跟蹤器的,如果需要在DEBUG版下打開跟蹤器,只需要將OGRE_MEMORY_TRACKER_DEBUG_MODE設(shè)置為1。而根據(jù)OgreMemoryAllocatorConfig.h文件中內(nèi)存操作宏的設(shè)置():
#if?OGRE_DEBUG_MODE??? //語句1
…//詳見源文件
#else?// !OGRE_DEBUG_MODE
…
#endif?// OGRE_DEBUG_MODE
即便是打開了OGRE_MEMORY_TRACKER_RELEASE_MODE宏,跟蹤器也不能記錄內(nèi)存分配語句所在文件名、行號和函數(shù)名,即不能正常工作。如果需要在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;
}
現(xiàn)開啟跟蹤器宏開關(guān),即將OGRE_MEMORY_TRACKER_DEBUG_MODE?和?OGRE_MEMORY_TRACKER_RELEASE_MODE?都置為1(須重新編譯)。該代碼正確釋放了所有內(nèi)存,不存在內(nèi)存泄漏。如果將代碼中釋放內(nèi)存的語句全部注釋掉,則在Debug版下生成的OgreLeaks.log文件的內(nèi)容為:
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文件的內(nèi)容為:
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版下,跟蹤器正常工作,順利的檢測出全部四處內(nèi)存泄漏,而在Release版下則不能正常工作。將“#if OGRE_DEBUG_MODE”改為“#if OGRE_MEMORY_TRACKER”后,重新在Release版下測試,跟蹤器便能正常工作,生成的OgreLeaks.log的內(nèi)容為:
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?來分別分配和釋放內(nèi)存,而并非前文所說的OGRE_DELETE_T,原因是因?yàn)閷τ趇nt,double等基本類型來說,是沒有析構(gòu)函數(shù)的,而OGRE_DELETE_T宏是要調(diào)用相應(yīng)析構(gòu)函數(shù)的。
2. 測試代碼中,若將using std::string;注釋掉,并將相應(yīng)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 !!!? 同樣是因?yàn)镺GRE_DELETE_T宏要調(diào)用basic_string類的析構(gòu)函數(shù)。類似情況還有在使用std::fostream,std::fistream等等時。
轉(zhuǎn)載于:https://www.cnblogs.com/zhehan54/p/5656911.html
總結(jié)
以上是生活随笔為你收集整理的【转载】ogre内存管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis安装(CentOS7/tar.
- 下一篇: ASP.NET Core 发布至Linu