C内存泄漏

如果不再使用已分配的内存却没有将其释放就会发生内存泄漏,导致内存泄漏的情况可能如下:

  • 丢失内存地址;
  • 应该调用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处的内存,程序已经没有地方持有这个地址。

enter image description here

图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所示,分配内存的起始地址丢失了。

enter image description here

图2-4:丢失动态分配的内存的地址

隐式内存泄漏

如果程序应该释放内存而实际却没有释放,也会发生内存泄漏。如果我们不再需要某个对象但它仍然保存在堆上,就会发生隐式内存泄漏,一般这是程序员忽视所致。这类泄漏的主要问题是对象在使用的内存其实已经不需要了,应该归还给堆。最差的情况是,堆管理器可能无法按需分配内存,导致程序不得不终止。最好的情况是我们持有了不必要的内存。

在释放用struct关键字创建的结构体时也可能发生内存泄漏。如果结构体包含指向动态分配的内存的指针,那么可能需要在释放结构体之前先释放这些指针,指针和结构体会展示示例。

赞(2)

评论 抢沙发

评论前必须登录!

 

C指针