案例一

作者:老王

如果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. 2、gitlab 新建项目

    一.创建项目 1.访问gitlab并登录 http://git.xh.com/ 2.点击 Projects -> Starred projects 每个版本的gitlab不太一样但位置都差不多 ...

  2. ajax跨域的解决办法

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content ...

  3. jekyll安装及使用

    清除旧版Ruby,若存在 yum remove ruby 若为源码,使用如下命令 cd <your-ruby-source-path> make uninstall 下面开始安装Ruby ...

  4. Python+Selenium 自动化实现实例-获取测试对象的Css属性

    #coding:utf-8 '''获取测试对象的css属性场景 当你的测试用例纠结细枝末节的时候,你就需要通过判断元素的css属性来验证你的操作是否达到了预期的效果.比如你可以通过判断页面上的标题字号 ...

  5. Windows内核分析——内核调试机制的实现(NtCreateDebugObject、DbgkpPostFakeProcessCreateMessages、DbgkpPostFakeThreadMessages分析)

    本文主要分析内核中与调试相关的几个内核函数. 首先是NtCreateDebugObject函数,用于创建一个内核调试对象,分析程序可知,其实只是一层对ObCreateObject的封装,并初始化一些结 ...

  6. linux中使用rm命令将文件移到回收站的方法

    今天在终端下,看到我的用户目录下有个-的文件夹(maven生成),相要删除收回点空间,习惯性的用命令 rm -rf ~ ,一回车,猛然想起的时候已经来不及了,世界一下子清静了,想死的心都有了! 没错, ...

  7. 【转载】retrofit 2 源码解析

    retrofit 官网地址:http://square.github.io/retrofit/ retrofit GitHub地址:https://github.com/square/retrofit ...

  8. java 简单类

    package 面向对象编程_封装性; //1.类名称必须存在有意义,例如Book.Emp //2.类之中所有的属性必须用private封装,封装后的属性必须提供有setter和getter方法 // ...

  9. react篇章-React 组件-复合组件

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...

  10. java _循环练习和数组练习

    练习 1.输出所有的水仙花数,所谓水仙花数是指一个数3位数,其每位数字立方和等于其本身,如153 = 1*1*1 + 3*3*3 + 5*5*5(很经典的题目) 分析: 通过观察发现,本题目要实现打印 ...