内存泄漏 一、内存泄漏的危害:
内存泄漏会导致当前应用程序消耗更多的内存,使得其他应用程序可用的内存更少了 。
如果有个进程可用的内存不够,就会触发Linux操作系统的直接/后台内存回收(即将一些内存页的数据写到磁盘里,那么该页也就可用了,脏页回写) 。虽然后台回收是异步的不阻塞当前进程,但是内存还是不够会触发直接内存回收,最后内存泄漏积累到一定程度,会直接触发OOM,该机制会杀掉那些实时占用内存大的进程 。
而且,即使没有OOM,无论是直接回收还是后台回收,都需要磁盘I/O而且需要多执行额外的回收线程,使系统性能下降 。
如果直接内存回收后,空闲的物理内存仍然无法满足此次物理内存的申请,那么内核就会放最后的大招了 ——触发 OOM (Out of )机制 。
还有资源泄漏:
比如没有关闭文件,程序提前或报错或忘记关闭,则可能导致想写入文件的数据没有真正落盘,从而丢失数据 。
二、内存泄漏举例:
1,在free()前就返回了,或者是报错并退出程序 。要在程序的所有路径上(if()的各个条件)都执行资源释放操作 。
2,在析构函数中未执行内存释放操作 。在构造函数中申请了堆内存或者打开了文件,在析构函数中忘了释放资源 。
3,基类的析构函数未声明为虚函数 。
析构函数如果不声明为虚函数,可能会导致多态对象在删除时无法正确调用派生类的析构函数(如果子类构造函数里()了内存,然后在析构函数里free()),从而导致内存泄漏 。
4,循环引用导致内存泄漏,用解决 。如下示例:
class Contro {private:double* p;public:Contro() {p = new double[10];}~Contro() {delete[] p;std::cout << "in ~Contro" << std::endl;}// 类内类class SubContro {public:SubContro() {p = new double[10];}~SubContro() {delete[] p;std::cout << "in ~SubContro" << std::endl;}std::shared_ptr
发生循环引用,两个的引用计数输出都是2,所以main函数结束的时候,引用计数没有减为0,就不会调用二者的析构函数,导致资源泄漏 。
将类里的改成即可,后者不会增加引用计数,因此两个智能指针的引用计数都是1,然后main结束的时候,引用计数减少为0,然后执行析构函数,此时不会发生内存泄漏,输出如下:
contro use_count: 1sub_contro use_count: 2in ~Controin ~SubContro
三、避免内存泄漏的手段: 1. 静态代码检查工具 (1)对于大型项目,可以使用静态代码分析工具
像开源的有软件,集成了一些静态代码分析的工具
静态代码检查工具会从词法、语法、语义等多维度去对工程代码扫描分析,发现可能存在的问题,比如变量未定义、类型不匹配、变量作用域问题、数组下标越界、内存泄露等问题 。
既然是静态,那么就不是运行时 。但是是编译前还是编译后还是编译中?
其实都有,像商业软件“啄木鸟”是给源文件就行,然后它会在编译的过程中去检测语法,词法,以及最后生成的二进制 。
代码静态分析(SAST):可以简单的理解为在不执行程序的情况下,对源代码, 中间代码或者二进制代码进行分析的技术
- c++中在头文件中定义static变量
- 内存管理专题04 伙伴分配器原理
- linux内核异步内存回收的另一个思路:基于冷热文件的冷热区域精准的回收冷文件页
- 内存换出和缓冲区释放
- 分割一切模型 Fast SAM C++推理部署
- 数据结构 C++实现 基于不同策略的英文单词的词频统计和检索系统
- ddr3内存过时了吗
- ddr5内存频率
- iphone14运行内存
- android framework 系统native c/c++源码查看跳转工具