English 中文(简体)
致命错误:内存大小超出了134217728字节(CodeIgniter + XML-RPC)
原标题:
  • 时间:2009-02-18 13:33:44
  •  标签:

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

客户机POS基于PHPPOS,并且我已经实现了一个模块,该模块使用标准的XML-RPC库将销售数据发送到服务。服务器系统建立在CodeIgniter上,使用XML-RPC和XML-RPCS库来构建网络服务组件。每当我发送大量销售数据(从销售表中少至50行,以及每个销售中涉及的销售商品的单行)时,我会收到以下错误提示:

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

128M是php.ini中的默认值,但我认为这是一个巨大的数字。事实上,我甚至尝试将该值设置为1024M,但它只会花更长的时间来发生错误。

至于我所采取的步骤,我尝试禁用服务器端的所有处理,并将其配置为无论输入是什么都返回一个预先准备好的响应。但是,我认为问题在于数据的实际发送。我甚至尝试禁用PHP的最大脚本执行时间,但它仍然出现错误。

问题回答

通过 ini_set( memory_limit , -1 ); 更改 memory_limit 不是一个适当的解决方案。请不要这样做。 (Translated back to English: Changing the memory_limit by ini_set( memory_limit , -1 ); is not a proper solution. Please don't do that.)

你的PHP代码中可能存在内存泄漏问题,并且你告诉服务器只需使用它想要的所有内存。你根本没有解决问题。如果你监控服务器,你会发现它现在可能正在使用大部分的RAM甚至交换到磁盘。

你应该尝试追踪你的代码中有问题的部分,并修复它。

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

The correct way is to edit your php.ini file. Edit memory_limit to your desire value.

根据您的问题,128M(默认限制)已超出,因此您的代码存在严重问题,它不应该占用那么多的资源。

如果您知道它需要那么多,且希望允许设置memory_limit = 512M或更高,则应该没问题。

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

Permanently

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

如果你可以访问你的php.ini文件,你可以编辑memory_limit的值到你想要的值。

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

Temporary

你可以从PHP文件内部动态调整内存分配。只需编写如下代码:ini_set(memory_limit,128M);(或者任何你想要的分配量)。你可以通过将值设置为“ -1”来删除内存限制(尽管机器或实例限制仍然适用)。

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

当使用array_push将2250万条记录添加到数组中时,我在php.ini文件中将内存限制设为4G,但在大约2000万记录处不断遇到“内存耗尽”致命错误。为了解决这个问题,我添加了以下语句:

$old = ini_set( memory_limit ,  8192M );

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

该程序非常简单:

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

The fatal error points to line 3 until I boosted the memory limit, which eliminated the error.

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

通过将它从这个改为

memory_limit=4G

对于这个:

memory_limit=4096M

这在PHP 7中纠正了问题。

你可以通过在fastcgi/fpm上更改memory_limit来正确修复这个问题。

$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

到 (dào)

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

当您看到上述错误 - 特别是如果(尝试分配 __ 字节)的值很低,这可能是无限循环的指示器,例如调用自身而无法退出的函数:

function exhaustYourBytes()
{
    return exhaustYourBytes();
}

您的网站根目录:

ini_set( memory_limit ,  1024M );

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

; 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.ini文件中的memory_limit值,如果您的代码中有一部分可能使用大量内存,您可以在该部分运行之前删除memory_limit,然后在之后替换它。

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

在Drupal 7中,您可以通过位于您的sites/default文件夹中的settings.php文件修改内存限制。在约260行附近,您会看到这个:

ini_set( memory_limit ,  128M );

即使您的php.ini设置很高,如果在Drupal settings.php文件中没有设置,您也无法消耗超过128 MB。

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

memory_limit = -1

内存限制为-1表示没有设置内存限制。现在已达到最大值。 (Nèicún xiànzhì wèi -1 biǎoshì méiyǒu shèzhì nèicún xiànzhì. Xiànzài yǐ dádào zuìdà zhí.)

在您的网页顶部添加一行ini_set(memory_limit, -1);

你可以根据需要将内存设置为-1的替代位置,如16M等。

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

ini_set( memory_limit ,  -1 );

工作,但我们需要把它放在开头后面。

<?php

在您网站根目录下的index.php文件中添加标签。

PHP 5.3+ allows you to change the memory limit by placing a .user.ini file in the public_html folder. Simply create the above file and type the following line in it:

memory_limit = 64M

一些cPanel主机仅接受此方法。

崩溃页面?

将此翻译成中文:输入图像描述

当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

对于那些纳闷为什么这个小函数会导致内存泄漏的人,有时由于小错误,函数开始无限递归调用自身。

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

class Proxy {

    private $actualObject;

    public function doSomething() {

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

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

我在运行比之前的数据集小的数据时遇到了以下错误。

致命错误:允许的内存大小为134217728字节已耗尽(试图分配4096字节),位于C:workspaceimage_management.php的173行。

由于寻找故障原因,我想我应该提到不一定是以前答案中的技术解决方案,而可能是更简单的问题。就我而言,是由于Firefox。在运行程序之前,它已经占用了1,157 MB。

原來是我在幾天之內分多次觀看了一個50分鐘的視頻,這搞亂了一些東西。這是專家們可以毫不費力地修復的問題,但對我這樣的人來說,值得記住。

在我的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;"

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

有时候,在循环内实现yield可以解决问题,而不是改变PHP.ini文件以实现更大的内存存储。Yield的作用是以逐个读取的方式而非一次性储存所有数据,节省了大量的内存使用。

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

正确的方法:php5 -cli /pathToScript/info.php 的中文翻译是: php5 -cli /pathToScript/info.php 的正确方式:

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

将此翻译为中文:在WHM 11.48.4上更新memory_limit

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

因此,如果您的标题和页脚已包含在内,请在包含标题之前包含所有功能文件。

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

But suppose you want a general procedure for stopping such a loop early and reporting the error? You can simply instrument each of your loops (or at least the innermost loops) as discussed below.

在某些情况下,如在异常内部进行递归时, set_time_limit 失败,浏览器会继续尝试加载 PHP 输出,无论是使用无限循环还是致命错误消息,这是本问题的主题。

通过在代码开头降低允许的分配大小,您可能会防止致命错误,正如其他答案中讨论的那样。

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

无论你的程序是否终止,都可以通过在程序中插入BreakLoop()调用来操纵代码,以便找出导致问题的循环或递归。

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参数可以是您代码中的函数名称。 实际上并不是必需的,因为您将收到的错误消息将指向包含BreakLoop()调用的行。

出现此错误的原因是您的服务器配置具有非常低的内存限制。尝试将此添加到wp-config.php(在此文件中的

define( WP_MEMORY_LIMIT ,  96M );

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

define( WP_MEMORY_LIMIT ,  256M );

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

I found myself in a site that had problems that gave error 500 to modify only some products, the problem was that they had used very heavy images in those specific products, solution: 1.- Increase "memory_limit" in php.ini 2.- Lower the weight of the images. 3.- Adapt again "memory_limit" to an acceptable value "512M" at least for me more than enough.

现在重要的是要验证更改是否正在进行,因为除了在服务器上安装几个版本和几种类型的PHP之外,可能会修改其中一个,但它无法正常工作,这是因为您没有修改正确的php.ini文件。

你如何验证你修改的是正确的文件?

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

请务必记住,在更改php.ini文件后,建议重新启动Apache或Nginx。

Ubuntu:sudo服务apache2重启

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

I hope it helps colleagues who have this problem.

增加memory_limit 解决了问题。但是,我找不到内存限制。我直接从实时服务器上工作,所以如果您正在做同样的事情,在cPanel上,如果您转到软件 - MultiPHP INI编辑器并选择位置,则可以找到memory_limit。我将我的增加到了256M至512M。您也可以在此处找到说明。

我对 ini_set(memory_limit, size_you_want); 感到怀疑。

相反,我与ini_restore( memory_limit );结合使用。这将恢复在您的PHP配置中定义的memory_limit的原始值。https://www.php.net/manual/en/function.ini-restore.php





相关问题