你写了一个PHP脚本,一般都不用考虑内存泄露和垃圾回收的问题,因为一般情况下你的脚本很快就执行完退出了。

但在一些运行时间长,数据量大的时候,程序运行一段时间后,php脚本就占用了过多内存,然后就报错(PHP Fatal error: Allowed memory size of 134217728 bytes exhausted)退出了。一般来说,每个页面处理结束,新建的simple_html_dom对象就应该被销毁了——但是实际上没有,很明显,内存泄露发生了。

PHP的垃圾回收机制

PHP5.3之前使用的垃圾回收机制是单纯的“引用计数”,也就是每个内存对象都分配一个计数器,当内存对象被变量引用时,计数器+1;当变量引用撤掉后,计数器-1;当计数器=0时,表明内存对象没有被使用,该内存对象则进行销毁,垃圾回收完成。

“引用计数”存在问题,就是当两个或多个对象互相引用形成环状后,内存对象的计数器则不会消减为0;这时候,这一组内存对象已经没用了,但是不能回收,从而导致内存泄露。

PHP5.3开始,使用了新的垃圾回收机制,在引用计数基础上,实现了一种复杂的算法,来检测内存对象中引用环的存在,以避免内存泄露。

查看内存是否泄露

看是否有该释放的内存没有被释放,可以简单的通过 调用  memory_get_usage  函数查看内存使用情况来判断;memory_get_usage 函数返回的内存使用数据据说不是很准确,可以使用  php 的 xdebug 扩展来获得更准确翔实的内存使用情况。

class A{private $b;function __construct(){$this->b = new B($this);}function __destruct(){//echo "A destruct\n";}
}class B{private $a;function __construct($a){$this->a = $a;}function __destruct(){//echo "B descturct\n";}
}for($i=0;;$i++){$a = new A();if($i00 == 0){echo memory_get_usage()."\n";}
}

上面就构造了一个会产生环状引用的例子。每次创建一个A对象的实例a,a就创建一个B对象的实例b,同时让b引用a。这样,每个A对象永远被一个B引用,而每个B对象同时被一个对象A引用,引用环就这样产生了。

在PHP5.2的环境下执行这段代码,会发现内存使用在单调上涨,也没有A和B的析构函数被执行后输出的“A/B desctruct”信息;直到内存耗尽,输出“PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 40 bytes)”。

在PHP5.3的环境下执行这段代码,则发现内存使用在上跳下窜,但是永远没有超过一个限额。程序也会输出大量的“A/B desctruct”,这说明析构函数被调用了。

我的同事的程序中,就存在这种引用的环路,而他的脚本,实在php5.2.3下执行的。simple_html_dom工具中,有两个类,分别是simple_html_dom和simple_html_dom_node,前者中有一个数组成员变量nodes,数组中每个元素都是一个simple_html_dom_node对象;而每个simple_html_dom_node对象都有一个成员变量dom,该dom的值就是前面的simple_html_dom对象——这样就形成了一个漂亮的引用环,导致了内存泄露。解决的办法也很简单,就是simple_html_dom对象在使用完毕时,主动调用其clear函数,清空其成员变量nodes,环就被打破了,内存泄露也就不会发生了。

其他

1. 垃圾回收的时机

PHP中,引用计数为0,则内存立刻释放。也就是说,不存在环状引用的变量,离开变量的作用域,内存被立刻释放。环状引用检测则是在满足一定条件下触发,所以在上面的例子中,会看到使用的内存有大幅度的波动。也可以通过 gc_collect_cycles 函数来主动进行环状引用检测。

2. &符号的影响

显式引用一个变量,会增加该内存的引用计数:

$a = "something";
$b = &$a;

此时unset($a), 但是仍有$b指向该内存区域的引用,内存不会释放。

3. unset函数的影响

unset只是断开一个变量到一块内存区域的连接,同时将该内存区域的引用计数-1;在上面的例子中,循环体内部,$a=new A(); unset($a);并不会将$a的引用计数减到零;

4. = null 操作的影响

$a = null 是直接将$a 指向的数据结构置空,同时将其引用计数归0。

5. 脚本执行结束的影响

脚本执行结束,该脚本中使用的所有内存都会被释放,不论是否有引用环。

PHP的内存泄露问题与垃圾回收相关推荐

  1. 深度解析Python的内存管理机制:垃圾回收机制

    Python程序在运行时,需要在内存中开辟出一块空间,用于存放运行时产生的临时变量,计算完成后,再将结果输出到永久性存储器中.但是当数据量过大,或者内存空间管理不善,就很容易出现内存溢出的情况,程序可 ...

  2. python终结一个循环额_Python语言入门之内存管理方式和垃圾回收算法解析

    本文主要向大家介绍了Python语言入门之内存管理方式和垃圾回收算法解析,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 在列表,元组,实例,类,字典和函数中存在循环引用问题.有 ...

  3. JVM内存管理机制和垃圾回收机制

    JVM内存管理机制和垃圾回收机制 JVM结构 图片描述: java源码编译成class文件 class文件通过类加载器加载到内存 其中方法区存放的是运行时的常量.静态变量.类信息等,被所有线程共享 堆 ...

  4. 一文详解,jvm内存分代与垃圾回收原理

    jvm运行时数据区 Java程序启动后,本质上就是启动一个jvm进程,jvm会将自己管理的内存划分为几个区域,每个区域都有自己的用途.在程序运行时的内存区域主要可以划分为五个,分别是:方法区.堆.虚拟 ...

  5. Python内存管理方式和垃圾回收算法解析

    在列表,元组,实例,类,字典和函数中存在循环引用问题.有 del 方法的实例会以健全的方式被处理.给新类型添加GC支持是很容易的.支持GC的Python与常规的Python是二进制兼容的. 分代式回收 ...

  6. JVM堆内存控制/分代垃圾回收

    JVM的堆的内存, 是通过下面面两个参数控制的 -Xms 最小堆的大小, 也就是当你的虚拟机启动后, 就会分配这么大的堆内存给你  -Xmx 是最大堆的大小 当最小堆占满后,会尝试进行GC,如果GC之 ...

  7. PHP内存管理机制与垃圾回收机制

    转载:https://www.cnblogs.com/zk0533/p/5667122.html PHP内存管理机制 var_dump(memory_get_usage()); //获取内存 $a = ...

  8. python内存管理机制错误_Python内存管理机制和垃圾回收机制的简单理解

    一.内存管理机制 1.由c开发出来的cpython 2.include / objests 3.需要下载python源码包 4.Pyobject:float PyVarObject: 5.在pytho ...

  9. jvm对象从新生代到老年代_JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代...

    内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...

最新文章

  1. 许昌学院计算机科学住几人间,许昌学院宿舍条件,宿舍环境图片(10篇)
  2. RetinaFace笔记
  3. Windows核心编程 第十九章 DLL基础
  4. 腾讯云上午突发故障 称运营商光缆中断所致
  5. C++虽不会过时,但是真的难啊!
  6. vs2017字体最佳选择_如何为下一个项目选择最佳字体? 一个简单的游戏
  7. 正则表达式匹配(动规)
  8. linux撤销编译,linux重新编译内核
  9. mmo游戏开发应在profile下运行,才能保证正式运行不卡
  10. 海康威视错误代码0xf_技术讨论 | 看我如何重置海康威视IP摄像机的管理员密码...
  11. 虚拟机桥接模式网络配置
  12. JanusGraph对于Gremlin查询语言的介绍
  13. 完善计算机 实践性教学,计算机基础实践性教学分析论文
  14. 计算机信息专业致谢词,计算机专业毕业论文致谢词
  15. 使用Glide切换图片时闪动
  16. P9 力荐!阿里巴巴最新出品 776 页 JDK 源码 + 并发核心原理解析小册
  17. 入门互联网IT行业就业前景如何?
  18. 张小龙-年薪近3亿的微信之父,他是如何做到的?
  19. 电信云服务器重装系统,天翼云主机操作(二)
  20. Spring 教程01

热门文章

  1. 机器学习面试题集 - 如何进行 A/B 测试
  2. 多目标跟踪 | AI产品经理需要了解的CV通识(三)
  3. 干货丨深度学习初学者必读:究竟什么是张量?
  4. IMT-2030(6G)推进组发布《6G总体愿景与潜在关键技术》白皮书
  5. 图文详解并联机器人,你了解吗?
  6. 全球顶尖计算机科学家排名,中科大上榜人数全国第一
  7. 追加10亿!腾讯宣布设立15亿元“战疫基金”
  8. 美国《时代》周刊公布年度25大最佳发明名单
  9. 麻省、北大、清华等顶尖高校与企业 20 位强化学习专家齐聚,RLChina 2021 强化学习暑期课免费报名啦!
  10. 程序员的浪漫,你值得拥有!