什么是内存泄露
内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。
常见的内存泄露造成的原因
- 忘记 delete: 对于使用new创建的动态分配内存空间,在使用完毕后必须要用delete释放掉内存,否则会造成内存泄漏
- 多次new而仅释放一次: 当使用new关键字对某一个对象进行动态内存分配时,操作系统会从堆中分配出一段连续的内存空间,此时需要匹配同样的数量的delete对这些内存址进行释放
- 循环引用没有断开:两个或多个对象相互关联时,若不避免循环引用的产生,则程序就无法自动释放被占用的内存空间
- 指针悬挂:指针悬挂(又称“野指针”)是指指针变量仍然指向已经被释放的内存空间或者未被初始化的空间,这时候如果使用该指针,则会产生内存泄漏的风险等
如何避免内存泄漏?
- 尽量使用栈上分配对象: 栈上分配的对象不需要手动释放内存,当函数结束时会自动被系统回收内存空间。
- 使用智能指针:可以使用标准库的智能指针(如std::shared_ptr和std::unique_ptr)来管理动态内存,在使用动态内存时减少手动释放的工作量。C++11以后提供的move语义也可以更好地实现资源所有权的转移,并且尽可能的使用auto关键字将代码简化
- 手动管理内存:对于那些不得不用new操作符申请内存的情况,为了避免忘记delete操作导致内存泄漏,我们可以将new和delete的逻辑都封装在一个类中,利用RAII技术来管理动态分配内存。
内存泄漏检测
静态检测的方法
下载个cppcheck 软件,该方法就是将整个工程代码加载,然后判断的。只检测编译器无法发现的bug,检测malloc和free 是否匹配。
使用 mtrace 进行检测
在该方法当中,需要在代码中添加头文件 #include <mcheck.h> ,然后添加对应的函数setenv("MALLOC_TRACE", "output.log", 1); 以及 mtrace();然后进行编译,但是这个只能看到是否有内存泄漏,我还不知道如何定位是在哪个函数里。
使用 Valgrind 进行检测