内存泄漏
前面我们讲过,分配了一个内存块但是忘记释放这个内存块会导致严重的问题,这样的内存块将等到程序执行结束时才会被释放
如果这个程序运行很长时间(例如服务器,而且不是所有的操作系统都像windows一样每天都可以重启)且这个程序在运行过程中不断的申请新内存块(new),如果此时忘记释放那些已经不在使用的老内存块,老内存块将迟早将内存消耗殆尽,直接导致后边的new操作无法执行和程序崩溃!
这样的编程漏洞称作内存泄漏(memory leak)
作为 C++ 程序员,内存泄露始终是悬在头上的一颗炸弹。在过去几年的 C++ 开发过程中,由于我们采用了一些技术,我们的程序发生内存泄露的情况屈指可数。今天就在这里向大家做一个简单的介绍
内存是如何泄漏的
在c/c++的程序内存分配中,自顶向下分为代码段,数据段,栈区,栈保留区,动态链接库区,堆保留区,堆区.
C++程序中,主要涉及到的内存就是[堆Stack]和[栈Heap]
栈区(stack) :由 编译器自动分配和释放,存放的是 运行时函数分配的局部变量,函数参数,返回数据,返回地址等参数,其操作类似于数据结构中的栈。
堆区(heap):一般 由程序员手动分配,如果程序员没有释放,程序结束时可能由os回收,其分配类似于链表,手动分配的内存便是在堆中的
详见C++内存分配一文:https://blog.csdn.net/Chroniccandy/article/details/109053967
栈中内存的申请和释放:
通常来说,一个线程上的栈内存是有限的,通常为8MB左右(大小取决于运行环境),栈上的内存通常是由编译器自动管理的。当在栈上分配一个新的变量时,或进入一个函数时,栈的指针会向下移动(下压栈),相当于在栈上分配了一块内存。我们把变量分配在栈上,也就是利用了栈上的内存空间,当这个变量的生命周期结束的时候,栈的指针会上移,相当于回收了此块内存。
正是由于栈上的内存和分配和回收均是由编译器自动完成控制的,所以在栈上是不会发生内存泄漏的,只会发生栈 溢 出的情况(Stack Overflow),也就是分配的空间超过了规定的栈大小。
堆中内存的申请和释放:
堆中的内存是由程序直接控制的,程序可以通过[new/delete]来分配和回收内存,如果程序中通过[new]手动分配了一块内存,但忘记使用[delete]来回收内存,便会发生内存泄漏。
内存泄漏的常见类型
内存的泄漏可以分为四类:
1.常发性内存泄漏
即发生内存泄漏的代码会被多次重复的指执行,每次被执行的时候都会导致一块内存泄漏
2.偶发性内存泄漏
即发生内存泄漏的代码只有再某些特定环境和操作过程下才会发生(例如在释放分配的内存之前程序通过某条件跳出了函数体,导致内存无法被delete)。常发性和偶发性是相对的,对于特定的环境,偶发性的也许会变成常发性的,所以测试环境和测试方法对检测内存泄漏至关重要!
3.一次性内存泄漏
即发生内存的代码只会被执行一次,或者是由于算法上的缺陷,导致总会有且仅有一块内存发生泄漏(比如在类的构造函数中分配内存,在析构函数中却没有释放该内存,但是由于这个类只会使用一次,所以内存泄漏只会发生一次)
4