c++内存泄露和野指针

一、什么是内存泄漏:

总结就是new出来的内存没有通过delete合理的释放掉。

用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,不能被任何程序再次使用,直到程序结束。即所谓内存泄漏。 

注意:内存泄漏是堆内存的泄漏;

简单的说就是申请了一块内存空间,使用完毕后没有释放掉。它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,整个系统崩溃。由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了。

二、造成内存泄漏的原因

1、在类的构造函数和析构函数中没有匹配的使用new和delete关键字;

2、没有正确清除嵌套的对象指针;

3、在释放对象数组时在delete中未使用方括号[],正确是delete [] p;

4、指向对象的数组指针不等同于对象数组;

对象数组是指:数组中存放的是对象,只需要delete []p,即可调用对对象数组中的每个对象的析构函数释放空间。

指向对象的指针数组是指:数组中存放的是指向对象的指针,不仅要释放每个对象的空间,还要释放每个指针的空间,delete []p只是释放了每个指针,但是并没有释放对象的空间,正确的做法是通过一个循环,将每个对象释放后再将指针释放。

5、缺少拷贝构造函数:两次释放相同的内存是一种错误的做法,同时可能造成堆的崩溃。按值传递会调用拷贝构造函数,而引用传递不会。因此如果一个类里面有指针成员变量,要么必须显式的写拷贝构造函数和重载赋值运算符,要么禁用拷贝构造函数和重载赋值运算符。

6、缺少重载赋值运算符:

7、关于nonmodifying运算符重载的常见迷思

a.返回栈上对象的引用或指针,导致最后返回的是一个空引用或空指针,因此变成野指针

b.返回内部静态对象的引用

c.返回一个泄漏内存的动态分配的对象,导致内存泄漏,并且无法回收

解决这一类问题的办法是重载运算符函数的返回值不是类型的引用,而是类型的返回值,即应该是int而不是int &。

8、没有将基类的析构函数定义为虚函数

当基类指针指向子类对象时,如果基类的析构函数不是virtual的,那么子类的析构函数不会被调用,子类对象的资源没有正确被释放,因此会造成内存泄漏。

三、什么是野指针

野指针不是NULL指针,是指未初始化或未清零的指针,他指向的内存不是程序员想要的内存;野指针是非常危险的;

野指针的成因主要是三个:

一是指针变量未被初始化;任何指针变量在被创建时,不会主动被赋值为NULL指针,他的缺省值是随机的,乱指一气;所以指针变量在被创建时应当被初始化,要么初始化为NULL指针,要么让他指向一个合法的内存地址;

二是指针被free或者delete之后,没有置为NULL,让人误以为是一个合法的指针;free或delete只是将指针p指向的内存释放掉,但p指针本身并没有被干掉。通常会用if(p!=NULL)进行防错处理。但这里if语句并不起作用,因为p不是NUll指针,也不指向任何合法的地址;

1   #include<stdio.h>
 2   #include<stdlib.h>
 3 
 4  int main()
 5  {
 6     char *p=(char *)malloc(sizeof(char)*100);
 7    strcpy(p, “hello”); 
 8    printf(“%s ”,p); 
 9  free(p); // p 所指的内存被释放,但是p所指的地址仍然不变 
10  if(p != NULL) // 没有起到防错作用 
11     strcpy(p, “world”); // 出错 
12     printf(“%s \n”,p);
13 }

free()释放的是指针指向的内存!注意!释放的是内存,不是指针!这点非常非常重要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,前面我已经说过了,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。非常重要啊这一点!

三是指针操作超过了变量的作用范围,比如返回指向栈内存的指针就是野指针。

  在使用指针的时候还要注意的问题:

  1:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放.

      2:  在使用指针进行内存操作前记得要先给指针分配一个动态内存。

猜你喜欢

转载自blog.csdn.net/deft_hll/article/details/82707947