1.申请的内存多次释放
#include <iostream>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//... ...
//... ...
delete[] p;//只允许一次释放
//... ...
//... ...
delete[] p;//申请的内存多次释放, 程序出现异常
system("pause");
return 0;
}
解决方案:在开辟新内存的时候就写好释放内存语句,其他语句在这两句语句的中间编写,养成这样的习惯,可以最大化避免重复释放内存
2.内存泄漏
#include <iostream>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//2. 忘记 delete,内存泄漏
do{
}while(1==1);
system("pause");
return 0;
}
运行结果:
解决方法同1.
3.释放的内存不是申请时的地址
#include <iostream>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//3.释放的内存不是申请时的地址
for(int i=0; i<18; i++){
cout<<*(p++)<<endl;
}
delete [] p;
system("pause");
return 0;
}
运行结果
解决方法:在动态分配内存的时候,尽量不要使用指针++的方法来进行操作,可以使用比较常规的p[i],如下
#include <iostream>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//3.释放的内存不是申请时的地址
for(int i=0; i<18; i++){
cout<<p[i]<<endl;
}
delete [] p;
system("pause");
return 0;
}
运行结果
4.释放空指针
#include <iostream>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//4.释放空指针
// ... ...
if(1==0){ //比如文件能打开的情况
p1 = new char[2048];
}
//... ...
delete p1;//如果文件没有打开,则p1是空指针
system("pause");
return 0;
}
运行结果:有时不会出问题,但有时会出问题,所以有风险,这个行为本身是不可取的
解决方法:可以将删除的语句放到if语句的里面,哪里使用就在哪里释放。在上面这段代码中,内存空间是在if语句中分配的,所以按照第一种情况给出的方法,删除语句应该也在if语句的大括号中出现。
5.释放一个内存块,但继续引用其中的内容
#include <iostream>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//5.释放一个内存块,但继续引用其中的内容
delete[] p;
// ...继续码代码...
p[0]= '\0';//绝对禁止
system("pause");
return 0;
}
解决方法:暂时没想到很好的解决方法,尽量记住自己释放内存的位置,或者在保证安全的情况之下,尽量将要编写的语句放在释放语句的上面。也就是说,在编程的时候就在分配内存和释放内存两行代码的中间进行编写。
6.越界访问
#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
int main(){
int * p = new int[18];
p[0] = 0;
char *p1 = NULL;
//6.越界访问
memset(p, 0, 18*sizeof(int));
for(int i=0; i<18; i++){
cout<<*(p++)<<endl;
}
//误判
for(int i=0; i<18; i++){
cout<<*(p++)<<endl;
}
system("pause");
return 0;
}
运行结果:
解决方法:同3.