案例一

作者:老王

如果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. Robust Online Visual Tracking with a Single Convolutional Neural Network

    Abstract:这篇论文有三个贡献,第一提出了新颖的简化的结构损失函数,能保持尽量多的训练样本,通过适应模型输出的不确定性来减少跟踪误差累积风险. 第二是增强了普通的SGD,采用了暂时的选择策略来进 ...

  2. BeanUtils封装对象时一直提示ClassNotFoundException:org.apache.commons.beanutils.BeanUtils

    导包明明正确了,依赖包也全都导对了,还是出错. 困扰了3天. 后来看到这篇博文,https://blog.csdn.net/yanshaoshuai/article/details/81624890 ...

  3. POJ 3616 Milking Time(最大递增子序列变形)

    题目链接:http://poj.org/problem?id=3616 题目大意:给你时间N,还有M个区间每个区间a[i]都有开始时间.结束时间.生产效率(时间都不超过N),只能在给出的时间段内生产, ...

  4. Copy List with Random Pointer——技巧

    A linked list is given such that each node contains an additional random pointer which could point t ...

  5. 初涉yield

    function* a(i) { console.log('here we go'); yield i; // 必须有*,不然b会作为返回值,而不是执行 yield* b(i); yield i+10 ...

  6. 洛谷 P1469 找筷子 题解

    题目传送门 先排序一遍,再一个一个判断是否有偶数个.注意for循环要i+=2. #include<bits/stdc++.h> using namespace std; ]; int ma ...

  7. AC日记——825G - Tree Queries

    825G - Tree Queries 思路: 神题,路径拆成半链: 代码: #include <cstdio> #include <cstring> #include < ...

  8. Python中列表的各种方法

    列表是Python中一种常用的存储信息的方式,所以要熟练掌握列表的各种方法: 首先我们定义一个列表(name),然后练习里面的各种方法: >>> name = ["Sora ...

  9. 抽象工厂模式(Abstract Factory)C#实例

    抽象工厂模式(Abstract Factory)C#实例 本文出处http://www.dofactory.com/net/abstract-factory-design-pattern 一.场景描述 ...

  10. Spark 源码解析:TaskScheduler的任务提交和task最佳位置算法

    上篇文章<  Spark 源码解析 : DAGScheduler中的DAG划分与提交 >介绍了DAGScheduler的Stage划分算法. 本文继续分析Stage被封装成TaskSet, ...