Quantcast
Channel: C++博客-所有随笔
Viewing all articles
Browse latest Browse all 7882

游戏中内存泄漏的查找

$
0
0

     我们的这款游戏从开发到上线至今已有大概4年了,昨天发现代码中有new出来的对象没有delete,程序退出后VS输出栏中居然没有提示,难道程序中没有内存泄漏检察?进一步的求证确定了我的担忧(我是半路进的项目组)。在代码中加上_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF)后,VS的输出栏赫然显示了大量的内存泄漏。在动手解决内存泄漏之前,先复习一下有关new操作符重载的相关知识:

new 操作符按其可见性可分为全局的与局部的(类成员),我们可以对他们进行重载,下面是VS 2010中new.cpp中new操作符的声明

1 void * operator new( size_t size );     //1
2 void * operator new ( size_t size, int nBlockUse, const char * szFileName, int nLine ); //2


void main()
{
   
char * p = new char;    //调用第1个new
   p = new ( _NORMAL_BLOCK, __FILE__, __LINE__ ) char;  //调用第2个new
}

调用new时,传入的参数比new声明时的参数少了一个,即第一个参数,该参数是new的对象的大小,由编译器填写,禁止程序员自己插手。

 

对一个类重载new和delete

class Student
{
    
void * operator new( size_t size )  //3
    {
         std::cout 
<< __FUNCTION__ << std::endl;
         
return malloc( sizeof(Student) );
    }
};
Student * pS = new Student();    //调用Student类内部的new,即第3个new

 

当我们new一个自定义类时,如果该类重载了new操作符,则优先使用该类内部定义的new,如果这时非要调用全局的new操作符怎么办呢?可以在new前面加两个冒号:

pS = ::new Student();  //调用全局的new,第1个new

 

下面回到解决内存泄漏的步骤上:

1 在程序必定会执行的路径上加上:

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

不一定非得是程序的最开始处

2 使用上面给出的第2个new操作符,当程序退出时,它会在VS输出栏中注明是哪行代码引起的内存泄漏。即所有的new 都改为

new ( _NORMAL_BLOCK, __FILE__, __LINE__ )

 

完了。。。。。这样就可以了。

但是,我们程序已有的代码都写的是new,而不是new ( _NORMAL_BLOCK, __FILE__, __LINE__ )。


MFC中的解决方法:

#define new  new ( _NORMAL_BLOCK, __FILE__, __LINE__ )

这样好像是可以解决问题,但是我们游戏中用了Gamebryo游戏引擎,这个引擎中很多类内部重载了new操作符,并且还有如下的宏定义:

#define NiNew new( NI_MEMHINT_NONE, __FILE__, __LINE__ , __FUNCTION__ )

并且引擎自带的对象都是通过NiNew来创建的,如 NiNew NiAlphaProperty();

如果我们把new 宏定义成了new ( _NORMAL_BLOCK, __FILE__, __LINE__ ),那么碰到NiNew NiAlphaProperty()后,代码就被展开成为

new ( _NORMAL_BLOCK, __FILE__, __LINE__ )  ( NI_MEMHINT_NONE, __FILE__, __LINE__ , __FUNCTION__ ) NiAlphaProperty(); 当编译器试着与NiAlphaProperty类内部的new操作符去匹配时就抓瞎了,只能报错。

目前我能想到的办法就是自己再定义一个宏:

#define New   ::new ( _NORMAL_BLOCK, __FILE__, __LINE__ )

 

将代码中所有的new替换成New。不知道还有没有什么更好的办法呢?

额。。。。。。_CrtSetBreakAlloc()对大型的C++工程不太实用



warrior 2013-01-19 16:04 发表评论

Viewing all articles
Browse latest Browse all 7882

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>