我们在实际编程中经常会说到内存溢出和内存泄漏,特别对于C/C++程序来说(以下代码示例均为C/C++),因为这时我们会跟内存直接打交道。然而很多时候我们并不能完全搞明白这两个概念,有时甚至会将二者颠倒混淆。
其实从命名上也能明白内存溢出和内存泄漏的大概,举个可能并不恰当的例子。好比是往水缸里打水,本来这个缸只能装下5桶水,第5桶装完你还硬要装第6桶,缸里的水自然就溢出来了,此为“内存溢出”;缸里打满水后并没有人用,第二天发现缸里的水少了一半,第三天一滴不剩了,原来是缸底打了个洞忘补了(为什么要在缸底打洞呢?不为什么,好玩,任性)。这就好比是申请了一块内存忘记释放了,造成了“内存泄漏”。下面将简要解析一下这两个概念。
首先说说内存溢出,内存溢出简单的说,即指要求分配的内存超出了系统所能提供的,比如你申请了一个10字节的内存空间,你硬要往里塞11字节大小的数据,自然就满了,溢出了嘛(如代码示例1)。其实数组越界也是一种内存溢出,比如写数据时超出了数组范围(越界读数组数据并不算内存溢出)。数组填充越界以后,再往里塞的话,就会挤占栈内存(一般数组声明为局部变量,局部变量在栈区自动分配内存)。越界的部分被当作局部变量占用栈内存,因为栈是从RAM的底部往上长(存数据)的,而程序运行的其他数据是从顶部往下的,所以当栈越存越多,越积越高的时候,栈就会和程序运行时的数据碰头,二者占满整个RAM内存,此时栈再继续消耗,栈再向上长,直接覆盖掉程序运行时所需的变量,程序就要跑飞了。这么看来内存溢出也是很可怕的。
- void arr_test()
- {
- int arr[10];
- arr[10] = 10;
- }
接着说说内存泄漏,一般所说的内存泄漏是指堆内存的泄漏(Heap leak),在对堆上动态申请内存,使用后未及时释放,即会出现内存泄漏。顺带说一下,如果释放了指针所指内存,但是未立即将指针置为NULL,就会造成野指针(如代码示例2)。一次内存泄漏可能不会被察觉,可能也不会有什么危害,但是内存泄漏的累积会造成内存用竭,那后果就严重了。比如内存泄漏出现在循环体中。当然还另有一些其他形式的内存泄漏,如由于系统资源的泄漏(Resource leak )造成的内存泄漏等等。根据内存泄漏的发生频率,一般内存泄漏可分为以下4种:
常发性内存泄漏;
偶发性内存泄漏;
一次性内存泄漏;
隐式内存泄漏。
- 1 void heap-leap_test
- 2 {
- 3 char *p = (char *)malloc(sizeof(char));
- 4 //exe task
- 5 free(p);//若不释放指针p所指内存空间,则会造成内存泄漏。
- 6 p = NULL;//若不置指针p为NULL,则p就会成为野指针。
- 7 }