C语言中,malloc, alloc, free是c定义的一组内存管理的API函数,free可以释放calloc, malloc, realloc动态分配的空间,当你调用malloc、alloc分配内存时,不仅仅是从堆里面分配得到了可用内存,实际上内存管理子系统还会维护了内存列表(你定义的普通指针不会出现这个列表中)。
而对于使用new, GlobalAlloc之类的方式分配的内存可不可以使用free呢。我的回答是,尽量不要,大部分情况都会带来风险,这里面涉及new, malloc, GlobalAlloc, HeapAlloc, LocalAlloc,VirtualAlloc等函数的区别。
那么对于自己定义的普通指针呢,首先要说一下,你要释放的不是你定义的指针,而是你定义的指针指向的空间。至于你定义的普通指针是不是可以通过free释放,这个要看情况。如果你定义的指针指向动态分配的地址空间,则可以使用free释放指针指向的这段空间;否则,就不能使用free释放指针指向的空间。下面举个例子:
在C Primer Plus(第五版)十七章中有如下一段代码:
current = head
while (current != null )
{
free(current);
current = current->next;
}
printf(“Bye!\n”);
head是一个指向一个链表头元素的指针,这段代码的作用是释放这个链表malloc的内存。
current既然已经free了,怎么还可以使用current = current->next呢,而且并没有报错!
显然上段代码中存在错误,原因:
1.free只是释放了malloc所申请的内存,并没有改变指针的值
2.由于指针所指向的内存空间已经被释放,所以其他代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的区域,也成为野指针(野指针指指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为NULL避免)。
3.为了避免错误,所以最好在free之后,使指针指向NULL。
总结:也就是说current被free之后,其指向的内容还没有改变,所以还能取得到current->next的值,free只是使current指向的内容可以被其他代码改变,如果在free之后立即被其他代码改变的话,就不能正确的取到current->next的值了。没报错只是偶然现象,内存释放只是告诉OS该内存区域不再被本进程独占,可以被其他进程所使用。至于数据是否马上被改变,要看OS的实际调度情况。
更改:
temp= current->next;
free(current);
current = temp;
补充:
例1:char p = NULL; p = (char)malloc(1024); if (p != NULL) free(p);
例2:char p = NULL; char buf[1024]; p = (char)buf; free(p);
其中,例1是对的,例2是错误的。