内存泄露
使用malloc()、calloc()、realloc()动态分配的内存,如果没有指针指向他,就无法进行任何操作,这段内存会一直被程序占用,知道程序运行结束由操作系统回收。
请看下面代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *p = (char*)malloc(100 * sizeof(char));
p = (char*)malloc(50 * sizeof(char));
free(p);
p = NULL;
return 0;
}
该程序中,第一次分配100字节的内存,并将p指向他;第二次分配50字节的内存,依然使用p指向他。
这就导致了一个问题,第一次分配的100字节的内存没有指针指向他了,而且我们也不知道这块内存的地址,所以就再也无法找回了,也没法释放了,这块内存就成了垃圾内存,虽然毫无用处,但依然占用资源,唯一的办法就是等程序运行结束后由操作系统回收。
这就是内存泄露(Memory Leak),可以理解为程序和内存失去了联系,再也无法对他进行任何的操作。
内存泄露形象的比喻是“操作系统可提供给所有程序使用的内存空间正在被某个程序榨干”,最终结果是程序运行时间越长,占用内存空间越来越多,最终用尽全部内存空间,整个系统崩溃。
再来看一种内存泄露情况:
int *pOld = (int*) malloc( sizeof(int) );
int *pNew = (int*) malloc( sizeof(int) );
这两句代码分别创建了一块内存,并且将内存的地址传给了指针pOld和pNew。此时指针pOld和pNew分别指向这两块内存。
如果接下来进行这样的操作:
pOld = pNew;
pOld指针就指向了pNew指向的内存地址,这时候再进行释放内存的操作:
free(pOld)
此时释放的pOld所指向的内存空间就是原来pNew指向的,于是这块空间被释放掉了。但是pOld原来指向的那块内存空间还没有被释放,不过因为没有指针指向这块内存,所以这块内存就造成了丢失。
另外,你不应该进行类似下面这样的操作:
malloc( 100 * sizeof(int) );
这样的操作没有意义,因为没有指针指向分配的内存,无法使用,而且无法通过free()释放掉,造成了内存泄露。
总结
free()函数的用处在于实时的回收内存,如果程序简单,程序结束前也不会使用过多的内存,不会降低系统性能,那么也可以不写free()函数。当程序结束后,操作系统释放内存。
但是如果在开发大型程序时不写free()函数,后果是非常严重的。这是因为很可能在程序中要重复一万次分配10M的内存,如果每次进行分配后都使用free()函数释放用完的内存空间,那么整个程序只需要使用10MB内存就可以运行。但是如果不使用free()函数,那么程序就要使用100GB的内存!这其中包括绝大部分的虚拟内存,而由于虚拟内存的操作需要读写磁盘,因此,这样会极大的影响到系统的性能,系统因此可能崩溃。
因此,在程序中使用malloc()分配内存时都对应的写出一个free()函数是一个良好的编程习惯。这不但能体现在处理大型程序时的必要性,并能在一定程度上体现程序优美的风格和健壮性。