如果不再使用已分配的内存却没有将其释放就会发生内存泄漏,导致内存泄漏的情况可能如下:
- 丢失内存地址;
- 应该调用
free
函数却没有调用(有时候也称为隐式泄漏)。
内存泄漏的一个问题是无法回收内存并重复利用,堆管理器可用的内存将变少。如果内存不断地被分配并丢失,那么当需要更多内存而malloc
又不能分配时程序可能会终止,因为它用光了内存。在极端情况下,操作系统可能崩溃。
下面这个简单的例子可以说明这个问题:
char *chunk;
while (1) {
chunk = (char*) malloc(1000000);
printf("Allocating\n");
}
chunk
变量指向堆上的内存。然而,在它指向另一块内存之前没有释放这块内存。最终,程序会用光内存然后非正常终止,即使没有终止,至少内存的利用效率也不高。
丢失地址
下面的代码段说明了当pi
被赋值为一个新地址时丢失内存地址的例子。当pi
又指向第二次分配的内存时,第一次分配的内存的地址就会丢失。
int *pi = (int*) malloc(sizeof(int));
*pi = 5;
...
pi = (int*) malloc(sizeof(int));
图2-3说明了这一点,“前”和“后”分别表示在执行第二次malloc
之前和之后的程序状态。由于没有释放地址500处的内存,程序已经没有地方持有这个地址。
图2-3:丢失地址
下面这个例子是为字符串分配内存,将其初始化,并逐个字符打印字符串:
char *name = (char*)malloc(strlen("Susan")+1);
strcpy(name,"Susan");
while(*name != 0) {
printf("%c",*name);
name++;
}
然而每次迭代name
都会增加1,最后name
会指向字符串结尾的NUL
字符,如图2-4所示,分配内存的起始地址丢失了。
图2-4:丢失动态分配的内存的地址
隐式内存泄漏
如果程序应该释放内存而实际却没有释放,也会发生内存泄漏。如果我们不再需要某个对象但它仍然保存在堆上,就会发生隐式内存泄漏,一般这是程序员忽视所致。这类泄漏的主要问题是对象在使用的内存其实已经不需要了,应该归还给堆。最差的情况是,堆管理器可能无法按需分配内存,导致程序不得不终止。最好的情况是我们持有了不必要的内存。
在释放用struct
关键字创建的结构体时也可能发生内存泄漏。如果结构体包含指向动态分配的内存的指针,那么可能需要在释放结构体之前先释放这些指针,指针和结构体会展示示例。
评论前必须登录!
注册