错误一:对NULL指针的解引用操作
//例如
int* p = (int*) malloc(40); //动态开辟一个大小40个字节的内存空间
//但如果malloc开辟失败,比如所要开辟空间过大,此时malloc会返回NULL,即p=NULL
*p = 10; //此时对p进行解引用就是对NULL解引用,这是error的!
-----------------正确操作-----------------
int* p = (int*) malloc(40);
if(p == NULL){
return 0;
}//使用
//......
//使用完后不要忘记释放p指向的动态内存空间,并将p指向NULL
free(p);
p = NULL;
错误二:对动态开辟空间的越界访问
int* p = (int*) malloc(40);
if(p == NULL){
return 0;
}//对p进行使用
int i =0;
for(i = 0; i<=10; i++){
*(p + i) = i; //这里出现错误,因为p只开辟了40个字节的内存空间,而你实际访问了44个字节,造成越界访问。解决办法只能是你在使用过程中对p的内存空间大小小心使用!
}
free(p);
p = NULL;
问题三:对非动态开辟内存使用free释放
//我们知道,动态开辟内存是在堆上开辟,而非动态内存则在其它区上开辟
int a = 10; //a为局部变量,在栈上开辟内存
int* p = &a;
free(p) //error! //free只针对动态内存进行释放
问题四:使用free释放一块动态开辟内存的一部分
int* p = (int*) malloc(40);
if(p == NULL){
return 0;
}//对p进行使用
int i =0;
for(i = 0; i<10; i++){
*p++ = i;
}
free(p); //由于上面使用p++,此时p指向的地址已经不是动态内存的起始位置,此时释放p,会造成越界访问操作。
p = NULL;
问题五:对同一块动态内存多次free释放
int* p = (int*) malloc(40);
if(p == NULL){
return 0;
}//使用
free(p);
//.......
free(p); //此时对p进行二次释放,运行程序会崩溃。最稳妥的办法是每次释放p,都在后面加上p = NULL;
//错误解释
在C语言中,当你尝试对一个已经释放的指针进行重复释放时,程序的行为是未定义的(Undefined Behavior, UB)。这意味着程序可能会崩溃、可能看起来正常工作但实际上数据已经被损坏、或者可能发生其他任何不可预测的事情。
具体来说,当你使用如
free()
这样的函数释放一个指针指向的内存时,你实际上是在告诉内存管理器这块内存现在可以被重新分配给其他用途了。但是,free()
并不会将指针设置为NULL
或进行其他任何形式的“标记”来表示它已经被释放。指针仍然指向原来的内存地址,只是那块内存现在不再属于你的程序,并且可能随时被其他部分的程序覆盖或重新分配。------------------正确操作----------------
free(p);
p = NULL;
free(p); //此时free(NULL)相当于什么都没发生
问题六:动态开辟内存忘记释放(内存泄露)
int* p = (int*) malloc(40);
if(p == NULL){
return 0;
}//使用
//这里没有对p进行释放导致内存泄露
//内存泄露是一个很可怕的事情,它会一直消耗掉计算机的内存,当然不包括除堆区以外的内存,所以建议每次动态开辟内存,下一步就在后面写上释放的代码。