致命错误:134217728字节的允许内存大小耗尽(CodeIgniter+XML-RPC)

我有一堆客户端销售点(POS)系统,它们定期将新的销售数据发送到一个集中式数据库,该数据库将数据存储到一个大数据库中以生成报告。

客户端POS基于PHPPOS,我实现了一个模块,该模块使用标准的XML-RPC库将销售数据发送到服务。服务器系统构建在CodeIgniter上,并使用XML-RPC和XML-RPCS库作为Web服务组件。每当我发送大量销售数据(销售表中只有50行,sales_items中与销售中的每个项目相关的单行)时,我都会得到以下错误:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)

128M是php.ini中的默认值,但我认为这是一个很大的数字。事实上,我甚至尝试将此值设置为1024M,它所做的只是需要更长的时间来出错。

至于我采取的步骤,我尝试禁用服务器端的所有处理,并将其设置为无论输入如何都返回预制响应。然而,我认为问题在于数据的实际发送。我甚至尝试禁用PHP的最大脚本执行时间,但它仍然出错。

1797905 次浏览

在PHP脚本中很容易出现内存泄漏-特别是如果您使用抽象,例如ORM。尝试使用Xdebug分析您的脚本并找出所有内存的去向。

ini_set('memory_limit', '-1');覆盖默认的php内存限制

对于Drupal用户,这是Chris Lane的答案:

ini_set('memory_limit', '-1');

工作但我们需要把它刚开幕后

<?php

在站点根目录中的index.php文件中标记。

在Drupal 7中,您可以修改位于站点/默认文件夹中的settings.php文件中的内存限制。在第260行,您会看到:

ini_set('memory_limit', '128M');

即使您的php.ini设置足够高,如果Drupalsettings.php文件中没有设置,您也无法消耗超过128 MB的内存。

正确的方法是编辑您的php.ini文件。 将memory_limit编辑为您的期望值。

从您的问题来看,128M(默认限制)已被超过,因此您的代码存在严重问题,因为它不应该占用那么多。

如果你知道为什么需要那么多,你想让它设置memory_limit = 512M或更高,你应该很好。

memory_limit更改为ini_set('memory_limit', '-1');没有的正确解决方案。请不要这样做。

您的PHP代码可能在某个地方有内存泄漏,您正在告诉服务器只使用它想要的所有内存。您根本不会解决这个问题。如果您监控您的服务器,您会看到它现在可能正在使用大部分RAM,甚至交换到磁盘。

您可能应该尝试跟踪代码中的违规代码并修复它。

PHP 5.3+允许您通过在public_html文件夹中放置.user.ini文件来更改内存限制。 只需创建上述文件并在其中键入以下行:

memory_limit = 64M

某些cPanel主机只接受此方法。

启用这两行后,它开始工作:

; Determines the size of the realpath cache to be used by PHP. This value should
; be increased on systems where PHP opens many files to reflect the quantity of
; the file operations performed.
; http://php.net/realpath-cache-size
realpath_cache_size = 16k


; Duration of time, in seconds for which to cache realpath information for a given
; file or directory. For systems with rarely changing files, consider increasing this
; value.
; http://php.net/realpath-cache-ttl
realpath_cache_ttl = 120

PHP的内存分配可以永久调整,也可以临时调整。

永久

您可以通过两种方式永久更改PHP内存分配。

如果您有权访问php.ini文件,您可以将memory_limit的值编辑为您想要的值。

如果您无权访问php.ini文件(并且您的网络主机允许),您可以通过.htaccess文件覆盖内存分配。添加php_value memory_limit 128M(或任何您想要的分配)。

临时

您可以在PHP文件中动态调整内存分配。您只需拥有代码ini_set('memory_limit', '128M');(或任何您想要的分配)。您可以通过将值设置为“-1”来删除内存限制(尽管机器或实例限制可能仍然适用)。

您网站的根目录:

ini_set('memory_limit', '1024M');

当我从代码中删除以下行时,一切正常!

set_include_path(get_include_path() . get_include_path() . '/phpseclib');
include_once('Net/SSH2.php');
include_once('Net/SFTP.php');

这些行包含在我运行的每个文件中。当一个接一个地运行文件时,所有工作正常,但是当将所有文件一起运行时,我遇到了内存泄漏问题。不知何故,“include_once”一次不包含东西,或者我做错了什么…

您可以通过更改memory_limit在Fastcgi/fpm上正确修复此问题:

$vim /etc/php5/fpm/php.ini

更改内存,例如从128更改为512,见下文

; Maximum amount of memory a script may consume (128 MB)
; http://php.net/memory-limit
memory_limit = 128M

; Maximum amount of memory a script may consume (128 MB)
; http://php.net/memory-limit
memory_limit = 512M

当你看到上面的错误时-特别是如果(tried to allocate __ bytes)是一个低值,那可能是一个无限循环的指示器,就像一个函数调用自己没有出路:

function exhaustYourBytes()
{
return exhaustYourBytes();
}

如果您运行的是WHM驱动的VPS(虚拟专用服务器),您可能会发现您没有直接编辑PHP.INI的权限;系统必须这样做。在WHM主机控制面板中,转到服务配置PHP配置编辑器并修改memory_limit

在WHM 11.48.4上更新memory_limit

当将2250万记录添加到array_push数组中时,我一直在使用4G作为文件中的内存限制20M记录中出现“内存耗尽”致命错误php.ini.

$old = ini_set('memory_limit', '8192M');

在文件的顶部。现在一切正常。我不知道PHP是否有内存泄漏。那不是我的工作,我也不在乎。我只需要完成我的工作,这奏效了。

程序非常简单:

$fh = fopen($myfile);
while (!feof($fh)) {
array_push($file, stripslashes(fgets($fh)));
}
fclose($fh);

致命错误指向第3行,直到我提高了内存限制,这 删除错误。

对于那些想弄清楚为什么这个小函数会导致内存泄漏的人来说,有时由于一个小错误,一个函数开始递归地永远调用自己。

例如,一个代理类,它与将要代理它的对象的函数具有相同的名称。

class Proxy {


private $actualObject;


public function doSomething() {


return $this->actualObjec->doSomething();
}
}

有时你可能会忘记带那个小的实际Objec成员,因为代理实际上有那个doSomething方法,PHP不会给你任何错误,对于一个大类,它可以隐藏几分钟,以找出它泄漏内存的原因。

我发现在实际处理的文件中包含或要求_dbconnection.php__functions.php时很有用,而不是包含在标头中。它本身就包含在内。

因此,如果包含报头页脚,只需在包含标头之前包含所有功能文件。

像这样运行脚本(例如cron case):php5 /pathToScript/info.php会产生相同的错误。

正确方法:php5 -cli /pathToScript/info.php

崩溃页面?

在此输入图片描述

(当MySQL必须查询大行时就会发生这种情况。默认情况下,memory_limit设置为小,这对硬件来说更安全。)

您可以在增加php.ini之前检查系统现有内存状态:

# free -m
total       used       free     shared    buffers     cached
Mem:         64457      63791        666          0       1118      18273
-/+ buffers/cache:      44398      20058
Swap:         1021          0       1021

在这里,我增加了它,如下所示,然后执行service httpd restart来修复崩溃页面问题。

# grep memory_limit /etc/php.ini
memory_limit = 512M

我在比以前更小的数据集上运行时出现了下面的错误。

致命错误:允许的内存大小为134217728字节耗尽(尝试分配4096字节)在C:\workspace\image_management.php第173行

由于搜索错误将我带到这里,我想我应该提到它并不总是以前答案中的技术解决方案,而是更简单的东西。在我的情况下是Firefox。在我运行程序之前,它已经使用了1,157 MB。

事实证明,我在一段时间内一次看50分钟的视频,这把事情搞砸了。这是专家们不假思索地纠正的那种修复方法,但对于像我这样的人来说,这值得记住。

我一直收到这个错误,即使在php.ini中设置了memory_limit,并且使用phpinfo()正确读出值。

通过将其更改为:

memory_limit=4G

对此:

memory_limit=4096M

这纠正了PHP 7中的问题。

如果您的代码中有一部分可能会使用大量内存,而不是更改php.ini文件中的memory_limit值,您可以在该部分运行之前删除memory_limit,然后在运行之后替换它。

$limit = ini_get('memory_limit');
ini_set('memory_limit', -1);
// ... do heavy stuff
ini_set('memory_limit', $limit);

更改php.ini文件中的内存限制并重新启动Apache。重新启动后,从任何PHP文件运行phpinfo()函数以获得memory_limit更改确认。

memory_limit = -1

内存限制-1表示没有设置内存限制。它现在处于最大值。

在我的例子中,这是一个简单的函数编写方式的问题。内存泄漏可能是由为函数的输入变量分配一个新值引起的,例如:

/**
* Memory leak function that illustrates unintentional bad code
* @param $variable - input function that will be assigned a new value
* @return null
**/
function doSomehting($variable){
$variable = 'set value';
// Or
$variable .= 'set value';
}

只需在网页顶部添加ini_set('memory_limit', '-1');行。

您可以根据需要将内存设置为-1、16M等。

使用yield也可能是一种解决方案。参见生成器语法

有时在循环中实现yield可能会解决这个问题,而不是将PHP.ini文件更改为更大的内存存储。产量所做的不是一次转储所有数据,而是一个接一个地读取它,从而节省了大量内存使用。

对我来说,此错误消息的最常见原因是从PHP“for”语句中省略“++”运算符。这导致循环永远继续,无论您允许使用多少内存。这是一个简单的语法错误,但编译器或运行时系统很难检测到。如果我们考虑寻找它,很容易纠正!

但是假设您想要一个通用过程来提前停止这样的循环并报告错误?您可以简单地检测每个循环(或至少最里面的循环),如下所述。

在某些情况下,例如异常中的递归,set_time_limit失败,浏览器不断尝试加载PHP输出,要么使用无限循环,要么使用致命错误消息,这是本问题的主题。

通过在代码开头附近减少允许的分配大小,您可能能够防止致命错误,如其他答案中所述。

然后您可能会留下一个终止的程序,但仍然难以调试。

无论您的程序是否终止,通过在程序中插入BreakLoop()调用来检测您的代码,以获得控制并找出程序中的循环或递归导致问题。

断路器的定义如下:

function BreakLoop($MaxRepetitions=500,$LoopSite="unspecified")
{
static $Sites=[];
if (!@$Sites[$LoopSite] || !$MaxRepetitions)
$Sites[$LoopSite]=['n'=>0, 'if'=>0];
if (!$MaxRepetitions)
return;
if (++$Sites[$LoopSite]['n'] >= $MaxRepetitions)
{
$S=debug_backtrace(); // array_reverse
$info=$S[0];
$File=$info['file'];
$Line=$info['line'];
exit("*** Loop for site $LoopSite was interrupted after $MaxRepetitions repetitions. In file $File at line $Line.");
}
} // BreakLoop

$LoopSite参数可以是代码中函数的名称。这不是真的必要,因为您将收到的错误消息会将您指向包含BreopLoop()调用的行。

更改;memory_limit=512M;memory_limit=-1输入图片描述

这对服务器来说太危险了 您的PHP代码可能在某个地方有内存泄漏,您正在告诉服务器只使用它想要的所有内存。您根本不会解决这个问题。如果您监控您的服务器,您会看到它现在可能正在使用大部分RAM,甚至交换到磁盘。

我花了两年时间寻找解决办法,我发现这是因为我打电话给PDO时

$stmt->bindParam(":PERIOD", $period);

变量周期是一个

empty string ''

所以这个问题可能有多个根本原因,我给你的建议是尝试反复试验或二分法来寻找根本原因,删除代码并尝试搜索失败的行代码

更新:我在使用$pdo->Query()方法时也遇到了这个错误,我使用了$pdo->准备()并且工作得很好,所以,虽然我有

$sql = "SELECT * FROM COURSE_DETAILS where ACTIVE = 1 AND COURSE_DETAILS_ID = $id";
$stmt = getConnection()->query($sql);
$courseDetails = $stmt->fetchAll(PDO::FETCH_ASSOC)

然后我把这个改成

$sql = "SELECT * FROM COURSE_DETAILS where ACTIVE = 1 AND COURSE_DETAILS_ID = ?";
$stmt = getConnection()->prepare($sql);
$stmt->execute(array($id));

记忆错误神奇地消失了!

在我的Mac(Catalina-Xampp)上没有加载文件,所以我必须先这样做。

sudo cp /etc/php.ini.default /etc/php.ini
sudo nano /etc/php.ini

然后更改memory_limit = 512M

然后重新启动Apache并检查文件是否已加载

php -i | grep php.ini

结果是

Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini

最后检查

php -r "echo ini_get('memory_limit').PHP_EOL;"

这个问题是几年前提出的,所以虽然我的事实不一样,但我最近在循环内解析服务器上的html表时也收到了这个错误。错误的原因是HTML是使用双引号解析的,双引号连接到变量$table,同时在多行上连接字符串。

$table = "<table>\n";
$table .= "<tbody>\n";
foreach ($data as $item) {
$table .= "<tr>\n";
// this caused the Fatal Error: Allowed Memory Size of 134217728 Bytes Exhausted
$table .= "<td>$item->description</td><td>$item->qty</td>" .
$table .= "<td>$item->price_incl</td><td>$item->price->vat</td>" .
$table .= "<td>$item->price_excl</td><td>$item->available</td>" .
$table .= "</tr>\n";
}
$table .= "</tbody>";
$table .= "</table>\n";

上述错误对我来说很奇怪,但考虑到我已经将字符串连接到$table变量,现在我尝试这样做似乎很愚蠢。解决方案是要么删除第7行和第8行的变量连接,要么删除第6行、第7行和第8行的端线连接符号。

在我的情况下,它是一个完整的磁盘和mysql拉屎本身。

在释放磁盘空间、修复数据库并重新启动Apache后,我的网站再次正常工作!

一些开车经过的孩子设法淹没了我的日志,填满了我在虚拟机上留下的稀缺的500个可能字节。: D

出现此错误的原因是您的服务器配置的内存限制非常低。尝试将其添加到wp-config.php(将其放在此文件中的<? php之后):

define('WP_MEMORY_LIMIT', '96M');

请注意,此限制对于主题和主题附带的插件是可以的。如果您想启用其他插件,您可能需要进一步增加限制。

define('WP_MEMORY_LIMIT', '256M');

问候是一个非常常见的问题,因为如果您分配给php的内存很少,并且您的网站正在增长,则需要更多资源。

我发现自己在一个网站,有问题,给错误500修改只有一些产品,问题是,他们使用了非常沉重的图像在这些特定的产品,解决方案: 1.增加php.ini的“memory_limit” 2.-降低图像的重量。 3.-再次适应“memory_limit”到一个可接受的值“512M”至少对我来说绰绰有余。

现在重要的是,你验证更改正在进行,因为php除了有几个版本和几种类型的安装在服务器上,也许你修改一个,它不起作用,这是因为你没有修改正确的php.ini文件。

如何验证您正在修改正确的文件?

在prestashop仪表板转到高级设置/信息,您可以看到“内存限制”。

请记住,在php.ini文件中进行更改后,建议重新启动apache或Nginx。

ubuntu:sudo服务apache2重启

重要提示:永远不要像很多人在这里提到的那样设置“memory_limit=-1”。问题是,如果您对文件或模块有问题,您可能会处于一个连续的循环中,消耗所有服务器的内存和处理器。让我们举一个简单的例子:一个模块有一个错误,并调用一个函数,直到它不是正的,它一直在调用,这将创建一个无限循环,它永远不会停止这样做,因为php没有限制。

希望对有这个问题的同学有所帮助。