> 文章列表 > 【C++】-- 内存泄漏

【C++】-- 内存泄漏

【C++】-- 内存泄漏

目录

内存泄漏

内存泄漏分类

如何检测内存泄漏

如何避免内存泄漏


内存泄漏

#问:什么是内存泄漏?
        内存泄漏:指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费
一句话:

        内存泄漏通常是因为我们的疏忽,或者是一些程序的错误,而导致不再使用的内存没有释放。

(错误如:抛出的异常所导致,new的空间并未进行delete)

void MemoryLeaks()
{// 1.内存申请了忘记释放int* p1 = (int*)malloc(sizeof(int));int* p2 = new int;// 2.异常安全问题int* p3 = new int[10];Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.delete[] p3;
}
#问:内存泄漏是指针丢了还是内存丢了?
        是指针丢了,因为如果指针没有丢就不存在内存泄漏。,因为只要指针没有丢我们就还可以进行释放。
        内存会丢?是并不会的!内存都在进程地址空间的位置,Linux下进程地址空间还会根据页表结构然后与物理内存进行映射。它是一直都在那个位置,只是因为它的指针被我们所搞丢了,从而导致我们不用了,但是想释放都释放不了。于是系统以为我们在使用,而我们没有在使用,并且一直不会使用,于是内存泄漏,可用内存越来越少。
        内存还在,进程正常结束,内存也会释放
#问:内存泄漏有什么危害?
        内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
  • 僵尸进程:

        僵尸进程有内存泄漏,因为是僵尸进程,所以进程没有正常的释放,正常的结束,于是资源没有的得到释放。僵死进程的内核栈无法被释放掉(1K 或者 2K大小),因为在栈的最低端,有着thread_info结构,它包含着 struct_task 结构,这里面包含着一些退出信息。这个时候僵尸进程非常的多,系统就会越来越慢。

  • 长期运行:

        虽然进程结束,内存泄漏就会释放,但是有一些进程是会长期运行的。最怕的就是一次只会泄漏一点点,这样的泄漏在长期的运行下就会凸显出来。

内存泄漏分类

C/C++程序中一般我们关心两种方面的内存泄漏:

  • 堆内存泄漏(Heap leak)
        堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。
  • 系统资源泄漏
        指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

如何检测内存泄漏

linux下内存泄漏检测:linux下几款内存泄漏检测工具
windows下使用第三方工具:VLD工具说明
其他工具:内存泄漏工具比较

如何避免内存泄漏

  • 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。

        ps:这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智能指针来管理才有保证。

  • 采用RAII思想或者智能指针来管理资源。
  • 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项

        ps:检测工具的内部实现原理,申请内存用一个容器记录下来,释放内存时从容器中删除掉。程序结束前,或者没有任何任务时,容器中的资源可能就是内存泄漏的。

  • 出问题了使用内存泄漏工具检测。

        ps:不过很多工具都不够靠谱,或者收费昂贵。

总结: 
内存泄漏非常常见,解决方案分为两种:
  • 事前预防型,如:智能指针等。(打疫苗)
  • 事后查错型,如:泄漏检测工具。(做核酸)