IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

PHP内存耗尽错误分析

Hito's Blog 2016-03-21 23:50:24 累计浏览 3,227 次
本机暂存

   最近有人跟我反映主机上一个wordpress插件的使用过程中经常会出现错误,打开了php的dispaly_error功能之后,发现其报“Fatal error: Allowed memory size of 35389440 bytes exhausted(tried to allocate 1406507 bytes) in xxxxxx on line xxx”,意思是致命错误,内存被耗尽了。Google上搜索了一下,网上有很多这样的问题,答案也都一样,更改php的内存限制,把php.ini中的memory_limit改为更大的数值。

   但是这里有一个很大的问题,php允许访问的内存大小是35389440字节,而实际要分配的只有1406507字节。为什么要分配的内存比实际允许访问的内存小还会引发致命错误呢?

   PHP内存耗尽错误

   查了很多这方面的资料,发现很多这样搜索结果,都是实际要分配的内存要小于允许的内存,但是没有找到对此的说明。

   首先想到是不是PHP本身这个内存限制功能有bug,于是做了如下实验:
1,  生成一个10MB大小的文件 dd if=/dev/zero of=10mb bs=1M count=10
2,  生成如下php文件并访问:

<?php
ini_set("memory_limit","2M");
echo file_get_contents("./10mb");
?>

   发现其报错“Fatal error: Allowed memory size of 2097152 bytes exhausted (tried to allocate 10493952 bytes)”,这个报错和我们设置的2M的内存限制,实际要分配10M的情况是一样的。这说明内存限制本身功能是没有问题的,报错的数据和实际的数据是能对上号的。

   那么,上面的问题出在哪里呢?为什么实际要分配的内存比限制的内存要小,还会导致出错?又查了一下php关于memory_limit的说明1:
This sets the maximum amount of memory in bytes that a script is allowed to allocate. This helps prevent poorly written scripts for eating up all available memory on a server. Note that to have no memory limit, set this directive to -1.
这里也没有对上述问题进行说明,只是告诉我们memory_limit用来限制一个脚本中分配的内存大小用来保护服务器免受poorly written scripts的影响。也就是说memory_limit是限制单个PHP运行脚本的可访问内存大小的,那会不会存在一种可能,整个线程中的多个操作加起来的内存超过了总限制大小,但单个操作的内存又只占整个限制的很小一部分,而最后那根压死骆驼的稻草是PHP报错出来的,所以显示出试图访问内存小于限制的内存大小?为了验证这个猜想,我把上述PHP文件改成这样并访问:

<?php
ini_set("memory_limit","15M");
$a = file_get_contents("./10mb");
$b = file_get_contents("./10mb");
?>

   发现其报错“Fatal error: Allowed memory size of 15728640 bytes exhausted (tried to allocate 10493952 bytes)”,实际要分配10M内存,小于允许访问的15M,验证了前面的猜想。也就是说,程序在运行时如果超过设置的内存,PHP报错信息只会提示当前操作试图访问的内存大小。

   那么直接增加内存限制的大小就可以解决这个问题了,限制的大小可以通过在php的shutdown函数上注册memory_get_usage函数来统计网站的内存消耗,取一个合适的值即可。

参考资料

  1. memory limit

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,267)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,162)
  3. Java开发岗位面试题归类汇总 (累计阅读 22,155)
  4. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,407)
  5. Linux内存点滴 用户进程内存空间 (累计阅读 13,228)
  6. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
  7. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,788)
  8. 15个最好的免费开源电子商务平台 (累计阅读 12,540)
  9. Redis消息队列的若干实现方式 (累计阅读 12,085)
  10. 到底什么是MVC? (累计阅读 11,865)