案例一

作者:老王

如果PHP对象存在递归引用,就会出现内存泄漏。这个Bug在PHP里已经存在很久很久了,先让我们来重现这个Bug,代码如下:

<?php
class Foo {
function __construct() {
$this->bar = new Bar($this);
}
} class Bar {
function __construct($foo) {
$this->foo = $foo;
}
} for ($i = 0; $i < 100; $i++) {
$obj = new Foo(); unset($obj); echo memory_get_usage(), "
";
}
?>

运行以上代码,你会发现,内存使用量本应该不变才对,可实际上却是不断增加,unset没有完全生效。

现在的开发很多都是基于框架进行的,应用里存在复杂的对象关系,那么就很可能会遇到这样的问题,下面看看有什么权宜之计:

<?php
class Foo {
function __construct() {
$this->bar = new Bar($this);
} function __destruct() {
unset($this->bar);
}
} class Bar {
function __construct($foo) {
$this->foo = $foo;
}
} for ($i = 0; $i < 100; $i++) {
$obj = new Foo(); $obj->__destruct(); unset($obj); echo memory_get_usage(), "
";
}
?>

办法有些丑陋,不过总算是对付过去了。幸运的是这个Bug在PHP5.3的CVS代码中已经被修复了。

参考链接:http://bugs.php.net/bug.php?id=33595


案例二

作者:贵贵的博客

出现了一个PHP脚本占用系统内存50%

开始认为是哪个变量PHP没有自动释放,查看代码,里面有个类的函数是static的,加了设置为Null和unset后无效果。

用memory_get_usage方法一测试,才发现在每次数据库读取都会增加内存。

看了db类找到原因了,原来db对象是放在全局里的,在数据库读取时会在他里面记录下执行的SQL。全局的程序没有执行完毕是不会释放的,这个脚本又是常驻内存执行的,解决方法也简单取消记录这个SQL就可以了。

经验:对于全局变量在循环调用里的内存使用要注意

<?php
class db
{
public $sql; public function query($sql)
{
$this->sql[] = $sql;
}
} $db = new db();
while(1) {
echo "m1:".memory_get_usage()."
";
$db->query("select * from table");
echo "m2:".memory_get_usage()."
";
usleep(10000);
}

显然这不是内存泄漏的BUG,只是代码编码的问题。

【PHP内存泄漏案例】PHP对象递归引用造成内存泄漏的更多相关文章

  1. Objective-C MRC多个对象相互引用的内存管理

    在MRC环境下,假定CTRoom对象是CTPerson的一个成员变量,那么修改CTRoom对象时应注意,代码如下: - (void) setRoom:(CTRoom *) room { //需判断新旧 ...

  2. 读 Runtime 源码:对象与引用计数

    以前只是看了很多博客,这次打算看一下源码,并记录下来.想到哪里就读到哪里,写到哪里.读的代码版本是:objc runtime 680,可以从这里下载 https://github.com/RetVal ...

  3. python中循环引用导致内存泄漏小案例

    首先定义一个Person类和一个Dog类,然后分别实例化对象p和d,给p对象添加一个pet属性 给d对象添加一个master属性此时Person和Dog的应用计数都为2,当del p 和del d后P ...

  4. Java 理论与实践: 用弱引用堵住内存泄漏---转载

    要让垃圾收集(GC)回收程序不再使用的对象,对象的逻辑 生命周期(应用程序使用它的时间)和对该对象拥有的引用的实际 生命周期必须是相同的.在大多数时候,好的软件工程技术保证这是自动实现的,不用我们对对 ...

  5. 从urllib2的内存泄露看python的GC python引用计数 对象的引用数 循环引用

    这里会发现上述代码是存在内存泄露,造成的原因就是lz与ow这两个变量存在循环引用,Python 不知道按照什么样的安全次序来调用对象的 __del__() 函数,导致对象始终存活在 gc.garbag ...

  6. Java 理论与实践: 用弱引用堵住内存泄漏

    弱引用使得表达对象生命周期关系变得容易了 虽然用 Java™ 语言编写的程序在理论上是不会出现“内存泄漏”的,但是有时对象在不再作为程序的逻辑状态的一部分之后仍然不被垃圾收集.本月,负责保障应用程序健 ...

  7. 分析ThreadLocal的弱引用与内存泄漏问题

    目录 一.介绍 二.问题提出 2.1内存原理图 2.2几个问题 三.回答问题 3.1为什么会出现内存泄漏 3.2若Entry使用弱引用 3.3弱引用配合自动回收 四.总结 一.介绍 之前使用Threa ...

  8. 递归 与 js 对象的引用

    <script> //递归 function test(n) { if (n == 1) { return 1 } console.log(n) return n * test(n - 1 ...

  9. JVM内存回收对象及引用分析

    自动垃圾回收是Java相较于C++的一个重要的特点,想了解JVM的垃圾回收机制,首先我们要知道垃圾回收是回收什么地方的垃圾,我在我的上一篇博客<JVM内存区域划分>里面有写到JVM里面的内 ...

随机推荐

  1. 《深入理解Java虚拟机》笔记--第十二章、Java内存模型与线程

    主要内容:虚拟机如何实现多线程.多线程之间由于共享和竞争数据而导致的一系列问题及解决方案. Java内存模型:     Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储 ...

  2. leetcode 之Search in Rotated Sorted Array(四)

    描述 Follow up for ”Search in Rotated Sorted Array”: What if duplicates are allowed?    Would this aff ...

  3. xcode7 安装 KSImageNamed

    1.前往Xcode7的插件文件夹,路径如下: ~/Library/Developer/Xcode/Plug-ins 如果有KSImageNamed,右键删除 2.在终端直接输入命令行: default ...

  4. Jmeter----连接mysql数据库及常见问题处理

    jmeter要链接mysql数据库,首先得下载mysql jdbc驱动包,(注:驱动包的版本一定要与你数据库的版本匹配,驱动版本低于mysql版本有可能会导致连接失败报错) 本人的数据为5.7.18, ...

  5. beego离线安装及运行

    官网: https://beego.me/ 由于公司上不了网,啥都得下载到本地来弄. go的安装不多说了,GOPATH要设置好的. 先离线下载好https://github.com/astaxie/b ...

  6. 「Ionic」WebStorm的使用錯誤-

    前言:遇到這個錯誤,不要慌張,搶按照濤叔下面的方式處理就可以了. 1.Couldn't find ionic.config.json file. Are you in an Ionic project ...

  7. Robot Framework + Selenium2Lib

    Robot Framework + Selenium2Lib 最近一段时间,公司在推行自动化测试流程,本人有幸参与了自定义通用控件的关键字封装和脚本辅助编写.数据驱动管理.测试用例执行管理等一系列工具 ...

  8. Xpath,XQuery,DTD

    一.Xpath XPath 是一门在 XML 文档中查找信息的语言;XPath 是 XSLT 中的主要元素.XPath是W3C标准.1.七种类型节点:元素.属性.文本.命名空间.处理指令.注释.文档节 ...

  9. ref:Java安全之反序列化漏洞分析(简单-朴实)

    ref:https://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247484200&idx=1&sn=8f3201f44e ...

  10. Python学习之pillow库入门

    http://python.jobbole.com/84956/ 我还是搬运工......