释放内存两种方式:
new <--> delete
new [] <--> delete []
出错现象:
1.执行delete语句时,程序直接弹窗,崩溃。
2.执行delete语句时,程序卡死。将delete语句注释掉,又正常了,但发生了内存泄露。
原因分析:
1.数组首地址被无意更改。例如:int A[10]; A++;
2.作用域不同。例如:在函数A中new的内存 int p = new int;在函数B中delete p,此时函数B不认识标识符p。
3.重复delete。例如:在dll的外部对dll的资源进行delete,有可能dll内部自己做了delete操作,此时会重复delete。
4.内存越界。这是最常见的,new的空间太少,使用时超出范围,更改了不属于程序自己的地址上的值。如果更改的地址是系统关键区域,程序会马上崩溃;如果是一般的地址,系统不会马上检测出来,这样就埋了一个bug。
例如:VC分配内存时,除了本身的数据空间外,还会分配额外的管理内存。例如在所分配内存的前后会放置边界标识符0xfdfdfdfd。若越界操作,改变了边界外的值,破坏了管理内存,delete时会失败或卡死。如图所示:0xfdfdfdfd为边界标识符,0xcd 0xcd 0xcd为分配的内存,堆区分配的内存未初始化时,VC填充0xcd。前面的0x00000003为分配的内存大小,0x00000001为内存分配目的,0x000000ab为分配的内存编号
解决方法:
1.当传入的形参是数组时,能加const的就加const,防止在函数内部中的意外操作。
2.内存new和delete时,原则:谁申请谁释放。
3.在delete指针后,将指针置为NULL。例如:delete p; p = NULL;
4.内存越界情况太多了,不具体说了。一般情况,在new之后,需要判断分配内存是否成功。声明指针后,置为NULL,例如:int *p = NULL;
释放内存宏:
-
#define SAFE_DELETE(p)
do {delete (p); (p) =
NULL;}
while (
false)
-
#define SAFE_DELETE_ARRAY(p)
do {delete [] (p); (p) =
NULL;}
while (
false)
释放内存模板:
-
template<
class T > void SafeDelete( T*& pVal )
-
{
-
delete pVal;
-
pVal =
NULL;
-
}
-
-
template<
class T > void SafeDeleteArray( T*& pVal )
-
{
-
delete[] pVal;
-
pVal =
NULL;
-
}