求助:PHP内存溢出问题Fatal error:Out of c outofmemoryerror

http://onwise.xyz/
PHP内存溢出解决方案
一.内存溢出解决方案
在做数据统计分析时,经常会遇到大数组,可能会发生内存溢出,这里分享一下我的解决方案。还是用例子来说明这个问题,如下:
假定日志中存放的记录数为500000条,那么解决方案如下:
ini_set(‘memory_limit’,’64M’); 
set_time_limit(600);
$farr = $Uarr = $Marr = $IParr = $data = $_sub = array();
$spt = ”$@
$root = ”/Data/webapps/VisitLog”;
$path = $dpath = $fpath = NULL;
$path = $root.”/”.date(“Y-m”,$timestamp);
$dpath = $path.”/”.date(“m-d”,$timestamp);
for($j=0;$j&24;$j++){
$v = ($j & 10) ? ”0″.$j : $j;
$gpath = $dpath.”/”.$v.”.php”;
if(!file_exists($gpath)){
$arr = file($gpath);
array_shift($arr);
$farr = array_merge($farr,$arr);
unset($arr);
if(empty($this-&farr)){
echo ”&p&&center&没有相关记录!&/center&&/p&”;
while(!empty($farr)){
$_sub = array_splice($farr, 0, 10000);
for($i=0,$scount=count($_sub);$i&$scount;$i++){
$arr = explode($spt,$_sub[$i]);
$Uarr[] = $arr[1];
$Marr[] = $arr[2];
$IParr[] = $arr[3].” |$nbsp;”.$arr[1];
unset($_sub);
unset($farr);
这里,不难看出,一方面,我们要增加PHP可用内存大小,另一方面,只要我们想办法对数组进行分批处理,分而治之,将用过的变量及时销毁(unset),一般是不会出现溢出问题的。
另外,为了节省PHP程序内存损耗,我们应当尽可能减少静态变量的使用,在需要数据重用时,可以考虑使用引用(&)。再一点就是:数据库操作完成后,要马上关闭连接;一个对象使用完,要及时调用析构函数(__destruct())。
二.unset销毁变量并释放内存问题
PHP的unset()函数用来清除、销毁变量,不用的变量,我们可以用unset()将它销毁。但是某些时候,用unset()却无法达到销毁变 量占用的内存!我们先看一个例子:
$s=str_repeat('1',255);
$m=memory_get_usage();
unset($s);
$mm=memory_get_usage();
echo $m-$mm;
最后输出unset()之前占用内存减去unset()之后占用内存,如果是正数,那么说明unset(s)已经将s从内存中销毁(或者说,unset()之后内存占用减少了),可是我在PHP5和windows平台下,得到的结果是:0。这是否可以说明,unset(s)并没有起到销毁变量s所占用内存的作用呢?我们再作下面的例子:
$s=str_repeat('1',256);
$m=memory_get_usage();
unset($s);
$mm=memory_get_usage();
echo $m-$mm;
这个例子,和上面的例子几乎相同,唯一的不同是,s由256个1组成,即比第一个例子多了一个1,得到结果是:272。这是否可以说明,unset(s)已经将$s所占用的内存销毁了?
通过上面两个例子,我们可以得出以下结论:
结论一、unset()函数只能在变量值占用内存空间超过256字节时才会释放内存空间。
那么是不是只要变量值超过256,使用unset就可以释放内存空间呢?我们再通过一个例子来测试一下:
$s=str_repeat('1',256);
$m=memory_get_usage();
unset($s);
$mm=memory_get_usage();
echo $p.'&br /&';
echo $m-$mm;
刷新页面,我们看到第一行有256个1,第二行是0,按理说我们已经销毁了s,而p只是引用s的变量,应该是没有内容了,另外,unset(s)前后内存占用没变化!现在我们再做以下的例子:
$s=str_repeat('1',256);
$m=memory_get_usage();
$mm=memory_get_usage();
echo $p.'&br /&';
echo $m-$mm;
现在刷新页面,我们看到,输出p已经是没有内容了,unset()前后内存占用量之差是272,即已经清除了变量占用的内存。本例中的s=null也 可以换成unset(),如下:
$s=str_repeat('1',256);
$m=memory_get_usage();
unset($s);
unset($p);
$mm=memory_get_usage();
echo $p.'&br /&';
echo $m-$mm;
我们将s和p都使用unset()销毁,这时再看内存占用量之差也是272,说明这样也可以释放内存。那么,我们可以得到另外一条结论:
结论二、只有当指向该变量的所有变量(如引用变量)都被销毁后,才会释放内存。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!博客分类:
以前追踪过这个问题,但是那个时候工具用的不太好,没看的这么细,这次搞的比较细,修正了偶以前的看法.于是写小文一篇总结一下.
PHP偶尔会爆一下如下 错误Allowed memory size of
xxx bytes exhausted at xxx:xxx (tried to allocate xxx bytes)
不想看原理的,直接跳到最后看总结.
这个报错信息的意思是是说,若ini配置的memory_limit(内存限制) 大于 AG(allocated_memory),就报错
AG(allocated_memory) += rs;
if (AG(memory_limit)&AG(allocated_memory)) {
int php_mem_limit = AG(memory_limit);
AG(allocated_memory) -= rs;
if (EG(in_execution) && AG(memory_limit)+1048576 & AG(allocated_memory)){
AG(memory_limit) = AG(allocated_memory) + 1048576;
if (file) {
zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted
at %s:%d (tried to allocate %d bytes)", php_mem_limit, file, lineno, s);
zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted
(tried to allocate %d bytes)", php_mem_limit, s);
if (file) {
fprintf(stderr, "Allowed memory size of %d bytes exhausted
at %s:%d (tried to allocate %d bytes)n", php_mem_limit, file, lineno, s);
fprintf(stderr, "Allowed memory size of %d bytes exhausted
(tried to allocate %d bytes)n", php_mem_limit, s);
memory_limit很简单,就是PHP可用的内存..AG(allocated_memory)是什么呢?是不是已经使用的内存,恩,我们用代码验证一下
PHP_FUNCTION(memory_get_usage) {
RETURN_LONG(AG(allocated_memory));
这下就清晰明了,还不懂的,查php手册,看memory_get_usage的说明
到底什么时候设置AG(allocated_memory)呢,具体代码就不贴了,太繁琐,是在emalloc函数中调用了第一段代码,看第一行代码,那里的rs就是每次tried to allocate %d bytes对应的s变量(你要申请的实际空间)的align对齐,具体计算方法:rs = (s+7) & ~0x7,也就是必须是8的倍数,不足则补足,这样做的好处是符合64位机器的要求,可以加速运算,例如 s =1,那么运算出来的rs =8 ,具体的,可以自己用PHP写个函数计算(0×7是16进制写法).
总结:既然知道了怎么回事,就好解决了,在开启 –enable-memory-limit情况下,会出这个错误,把配置文件直接设置memory_limit,或者在代码中设置ini_set(‘memory_limit’, ‘value’)都可以,省事的办法就是设置配置文件(如php.ini)
而且建议开启–enable-memory-limit,若这个不开启,PHP的内存限制就处于”裸跑”状态,可能会出现著名的out of memory错误.
使用脚本语言最大的好处之一就是可利用其拥有的自动垃圾回收机制(释放内存)。你不需要在使用完变量后做任何释放内存的处理,PHP会帮你完成。
当然,我们可以按自己的意愿调用 unset() 函数来释放内存,但通常不需要这么做。
不过在PHP里,至少有一种情况内存不会得到自动释放,即便是手动调用 unset()。详情可考:。
如果两个对象之间存在着相互引用的关系,如“父对象-子对象”,对父对象调用 unset() 不会释放在子对象中引用父对象的内存(即便父对象被垃圾回收,也不行)。
有些糊涂了?我们来看下面的这段代码:
class Foo {
function __construct()
$this-&bar = new Bar($this);
class Bar {
function __construct($foo = null)
$this-&foo = $
while (true) {
$foo = new Foo();
unset($foo);
echo number_format(memory_get_usage()) . "\n";
运行这段代码,你会看到内存使用率越来越高越来越高,直到用光光。
33,551,616
33,551,976
33,552,336
33,552,696
PHP Fatal error: Allowed memory size of
bytes exhausted
(tried to allocate 16 bytes) in memleak.php on line 17
对大部分PHP程序员来讲这种情况不算是什么问题。
可如果你在一个长期运行的代码中使用到了一大堆相互引用的对象,尤其是在对象相对较大的情况下,内存会迅速地消耗殆尽。
Userland解决方案
虽然有些乏味、不优雅,但之前提到的 bugs.php.net 链接中提供了一个解决方案。
这个方案在释放对象前使用一个 destructor 方法以达到目的。Destructor 方法可将所有内部的父对象引用全部清除,也就是说可以将这部分本来会溢出的内存释放掉。
以下是“修复后”的代码:
class Foo {
function __construct()
$this-&bar = new Bar($this);
function __destruct()
unset($this-&bar);
class Bar {
function __construct($foo = null)
$this-&foo = $
while (true) {
$foo = new Foo();
$foo-&__destruct();
unset($foo);
echo number_format(memory_get_usage()) . "\n";
注意那个新增的 Foo::__destruct()方法,以及在释放对象前对 $foo-&__destruct() 的调用。现在这段代码解决了内存使用率一直增加的问题,这么一来,代码就可以很好的工作了。
PHP内核解决方案?
为什么会有内存溢出的发生?我对PHP内核方面的研究并不精通,但可以确定的是此问题与引用计数有关系。
在 $bar 中引用 $foo 的引用计数不会因为父对象 $foo 被释放而递减,这时PHP认为你仍需要 $foo 对象,也就不会释放这部分的内存……大概是这样。
这里确实可以看出我的无知,但大体意思是:一个引用计数没有递减,所以一些内存永远得不到释放。
在前面提到的 bugs.php.net 链接中我看到修改垃圾回收的过程将会牺牲极大的性能,因为我对引用计数了解不多,所以我认为这是真的。
与其改变垃圾回收的过程,为什么不用 unset() 对内部对象做释放的工作呢?(或者在释放对象的时候调用 __destruct()?)
也许PHP内核开发者可以在此或其他地方,对这种垃圾回收处理机制做出修改。
更新:Martin Fjordvald 在评论中提到了一个由 David Wang 为垃圾回收所写的补丁(其实它看起来更像“一整块布”——非常巨大。详情参见此邮件结尾的CVS导出信息。)确实(一封邮件),并受到了PHP内核开发成员的关注。问题是这个补丁要不要放到PHP5.3中并未得到。我觉得一个不错的折中方案就是在 unset() 函数中调用对象中的 __destruct() 方法;
浏览: 182753 次
来自: 杭州
貌似还是不行,再等等吧,amfphp要出2.0了
请问amfphp与php5.3.X搭配能用了吗?
非常感谢!
谢谢提示,我遇到的也是不能加密,用MAC地址代替之。
不错,要挖去了,哈哈
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'出现out of memory错误,怎样解决?
[问题点数:100分,结帖人dentliu]
本版专家分:0
结帖率 100%
CSDN今日推荐
本版专家分:336
本版专家分:697
本版专家分:691
本版专家分:0
结帖率 100%
本版专家分:0
结帖率 100%
本版专家分:0
结帖率 100%
本版专家分:26008
2002年9月 其他开发语言大版内专家分月排行榜第一
2011年10月 其他开发语言大版内专家分月排行榜第二2004年10月 其他开发语言大版内专家分月排行榜第二2003年7月 其他开发语言大版内专家分月排行榜第二
2011年9月 其他开发语言大版内专家分月排行榜第三2011年5月 其他开发语言大版内专家分月排行榜第三2004年7月 其他开发语言大版内专家分月排行榜第三2002年6月 其他开发语言大版内专家分月排行榜第三
本版专家分:0
结帖率 100%
匿名用户不能发表回复!|
CSDN今日推荐out of memory内存溢出已经普遍解决--坑之谷官网【龙之谷吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:1,923,279贴子:
out of memory内存溢出已经普遍解决--坑之谷官网
刚刚看到nvidia公司早在1月4日发布了G系列(即WIN7下所有的显卡)驱动,小弟激动得不得了。我们一直为着out of memory感到头痛。如果你是N卡的,刷天启还是其他图出现out of memory,请按我下步骤做吧:说在前面的话:&&&&& 其实出现这情况最根本的问题是在于显卡公司和游戏开发公司编程上出现冲突,而并不能把责任推给WIN7系 统。我们一个显示编程如果跟对应的显卡公司开发的技术不一样的话,那么很抱歉,你游戏不能或者不能完全用到我的显卡驱动,致使你电脑里有了显卡也没有用,还得用微软的图形来代替显卡图形的处理。而恰好龙之谷这游戏的编程本身就和N卡公司技术发生冲突,所以你在运行这游戏的时候,仅仅是半驱动你的显卡,部分功能没办法用显卡处理!而1月4日N卡公司在WIN7下开发的显卡驱动技术就完全兼容了龙之谷,这样一来就龙之谷就可以完完全全驱动N卡公司的显卡了,所以自然而然的内存溢出和其他报错问题也就相应解决了!我想对A卡的朋友说,因为A卡技术本身都在XP下开发然后升级到WIN7的,所以出现内存溢出几率很少,如果A卡也出现,那也请耐心等待开发商的驱动开发。&&&& 以下是这次N卡驱动在1月4日对所有G系列的显卡做出的更新(转自N卡*网):英伟达™3D立体幻镜™(NVIDIA® 3D Vision™)游戏配置文件: Arcania: Gothic 4 跑跑卡丁车单机版 穿越火线 Darksiders DC Universe Online 龙之谷 Front Mission Evolved Guild Wars 2 Hank Haney's World Golf Lineage 2 Medal of Honor (2010) 多人版 Medal of Honor (2010) 单机版 NED Need for Speed Hot Pursuit 英伟达™(NVIDIA®)演示:外星人大战三角形 英伟达™(NVIDIA®)演示:无尽的都市 跑跑卡丁车 QQ炫舞 QQ Xian Xia Zhuan QQ&&& 仙侠传 天龙八部 TRON: Evolution Vizerra (全屏版) World Rally Championship 2010 寻仙英伟达™3D立体幻镜™(NVIDIA® 3D Vision™)游戏配置文件: Lost Planet 2 – 评级现已改为Fair Tom Clancy’s H.A.W.X.2 - 评级现已改为3D Vision Ready英伟达™速力™(NVIDIA® SLI) 专为下列PC游戏新增了英伟达™速力™(NVIDIA® SLI)配置文件:《外星人大战三角形》演示 《无尽的都市》演示 Lionheart: Kings Crusade Moscow Racer: Legends of USSR Rift: Planes of Telara Shaun White Skateboarding专为下列PC游戏增强了英伟达™速力™(NVIDIA® SLI)配置文件: Age of Conan Arcania: Gothic 4 Civilization V - DX11 Lost Planet 2 World Of Warcraft&&&& 可见N卡已经兼容了许多游戏。接下来要说到解决方法了:1,请大家登录N卡*网,网址是:2,确认你是哪个型号的显卡,然后把鼠标放在*网上的“驱动下载”,找到下标栏里的“试用版驱动程序”3,选择你的显卡类型,选择你的系 统类型,同时在“最新”选项中选择“全部”,然后点“搜索”4,找到最新的版本,并在标题上标有“BETA”字样的驱动,选择后进行下载。5,安装时请选用“自定义”→选择“清洁安装”这样你的老版本驱动就会被卸载然后换新驱动!即可解决(PS:执行以上操作时,请把以前你修改过的参数改回来,例如你修改过的虚拟空间等,都改成系统默认)新驱动解决的问题如下:①出现内存溢出out of memory的情况,经小弟测试天启等(连续进10多次),无限爆点交易所都不会出现这问题。②解决N卡全屏下使用输入法后会卡屏现象③完全驱动显卡,新显卡让你感觉画面更流畅!④解决突然出现画面卡死现象!以上解决方式仅限制N卡!希望楼主能让更多人看到,对于笔记本的朋友经常出现该问题更是解决得彻底!PS:不知道显卡型号自己打电话给你对应电脑的*网。笔记本电脑的别忘了后面有个(NOTEBOOK)的标志选择哦!
路过,自己挽回
楼主辛苦…
N卡能用来耍游戏么。。。。简直是折磨自己
贴吧热议榜
使用签名档&&
保存至快速回贴

我要回帖

更多关于 cv outofmemoryerror 的文章

 

随机推荐