登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Code@Pig Home

喜欢背着一袋Code傻笑的Pig .. 忧美.欢笑.记忆.忘却 .之. 角落

 
 
 

日志

 
 

[ogre] 用于debug的MemoryManager  

2008-08-19 00:33:42|  分类: 3d_ogre |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Ogre 中的 MemoryManager 仅用于 debug,检查是否存在泄漏、越界访问等非法情况,并不是优化用的小块内存分配器。

相关文件:
OgreMemoryManager.h/.cpp        MemoryManager 的实现
OgreMemoryMacros.h            用宏替换普通的 new/delete, malloc/free
OgreNoMemoryMacros.h            抵消 OgreMemoryMacros.h 的效果,还原普通的 new/delete, malloc/free(实现 MemoryManager 时需要)

OgrePrerequisites.h 中 #include "OgreMemoryManager.h",因此可以让所有模块都引入 MemoryManager。

启用 MemoryManager 的方法:
#define OGRE_DEBUG_MEMORY_MANAGER 1

=====================
wipeWithPattern(),将 sAllocUnit.actualAddress 所指向的内存全部写为 pattern 的内容。
dumpAllocations(),进程所申请的所有内存块的情况。

MemoryManager::dllocMem() 的时候会检查 new/delete, new []/delete [], malloc/free 是否匹配。
每两次 MemoryManager::allocMem() 之间,检查所有已分配的内存块是否存在越界访问(检查 padding 是被写坏)。

=====================
new       -->  MemoryManager::op_new_sc()  -->  MemoryManager::allocMem
new []    -->  MemoryManager::op_new_vc()  -->  MemoryManager::dllocMem
delete    -->  MemoryManager::op_del_sc()  -->  MemoryManager::allocMem
delete [] -->  MemoryManager::op_del_vc()  -->  MemoryManager::dllocMem

=====================
几个全局变量,决定了 MemoryManager 的整个运作机制:
struct sMStats;
sAllocUnit *reservoir;
sAllocUnit *hashTable[hashSize];
sAllocUnit **reservoirBuffer;
unsigned int reservoirBufferSize;

下面我们来一一分析之。

=====================
全局变量 struct sMStats; 包括了一些基本的统计信息。

totalReportedMemory - 当前申请的内存总数
totalActualMemory   - 当前实际的内存总数

peakReportedMemory  - 申请的内存总数的峰值
peakActualMemory    - 实际的内存总数的峰值

accumulatedXXXX     - 内存使用的积累总量(只增不减)

因此,当所有申请的内存释放后,totalActualMemory == 0,则没有内存泄漏。

=====================
每次 allocMem() 会判断 reservoir 中是否还有空闲 au,没有了则再申请 256 个,并将所申请的 256 个 au 放入 reservoirBuffer。
reservoir, 当前空闲的 sAllocUnit List (free list)
reservoirBuffer, 所有申请的 sAlloocUnit 的集合
reservoirBufferSize, 数组 reservoirBuffer[] 的大小



allocMem() 会根据 reportedSize 分配一个 actualSize 大小的内存,主要目的是产生了前后两块 padding,用以检查是否存在越界访问。


所有已经被征用的 au,会被放到全局变量 hashTable[] 中。程序退出时,如果 totalActualMemory != 0,则 hashTable 中的所有 au 都是泄漏的。

 

------------------

2008-09-07  补充  从 new/delete 中截取 __FILE__, __LINE__ 信息

今天和 nescafe 讨论 new/delete 无法如 malloc/free 一般,很好的获取 __FILE__, __LINE__ 这些信息。突然想到 OgreMemoryManager 其实很好地实现了此目的,只是我当时阅读代码时,并没有很好地理解这一段代码的用意。

因为语法的关系,我们无法像 malloc/free 一样,简单地弄个宏就搞定。

#define malloc(size) my_malloc(size, __FILE__, __LINE__)
#define free(p) my_free(p, __FILE__, __LINE__)

自然,想重载函数也是不行的。

void *operator new(size_t size, const char* file, const int line);
void operator delete(void *p, const char* file, const int line);

Ogre 则通过一个小小的 trick 做到了,呵呵,如下,我做了一个简化版本:

// ====== my_alloc.h =======

#ifndef MY_ALLOC
#define MY_ALLOC

void make_record(char const *file, int line, char const *func);

void *my_new(size_t size);
void my_delete(void * p);

inline void *operator new(size_t size)
{
    return my_new(size);
}

inline void *operator new[](size_t size)
{
    return my_new(size);
}

inline void operator delete(void *p)
{
    my_delete(p);    
}
inline void operator delete[](void *p)
{
    my_delete(p);
}


#define new    (make_record(__FILE__, __LINE__, __FUNCTION__), false) ? 0 : new
#define delete (make_record(__FILE__, __LINE__, __FUNCTION__), false) ? 0 : delete

#endif

 

// ====== my_alloc.cpp =======

#include "my_alloc.h"
#include <stdlib.h>
#include <stdio.h>

static char const * cur_file;
static int cur_line;
static char const * cur_func;


void make_record(char const *file, int line, char const *func)
{
    cur_file = file;
    cur_line = line;
    cur_func = func;
}

void *my_new(size_t size)
{
    printf("new() file = %s, line = %d, func = %s\n", cur_file, cur_line, cur_func);
    return malloc(size);
}

void my_delete(void * p)
{
    printf("new() file = %s, line = %d, func = %s\n", cur_file, cur_line, cur_func);
    free(p);
}

 

// ======== main.cpp =========

#include "my_alloc.h"

int main(void)
{
    int *p = new int;
    delete p;

    p = new int[10];
    delete [] p;

    return 0;
}

  评论这张
 
阅读(1526)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018