705

我有一堆客户销售点 (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 的最大脚本执行时间,但它仍然出错。

4

32 回答 32

782

更改memory_limitbyini_set('memory_limit', '-1');不是一个适当的解决方案请不要那样做。

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

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

于 2013-09-06T14:24:11.737 回答
218

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

于 2011-10-25T20:42:44.633 回答
149

正确的方法是编辑您的php.ini文件。编辑memory_limit您想要的值。

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

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

于 2013-03-21T07:29:08.153 回答
106

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

永久

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

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

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

暂时的

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

于 2014-03-09T14:55:54.870 回答
65

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

于 2009-02-18T14:42:12.133 回答
58

当使用 array_push 将 2250 万条记录添加到数组中时,我一直在使用4Gphp.ini 文件中的内存限制在大约 20M 条记录时出现“内存耗尽”致命错误。为了解决这个问题,我添加了语句

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

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

该程序非常简单:

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

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

于 2015-06-28T05:19:31.373 回答
48

即使使用memory_limitset in php.ini,并且使用 正确读取值,我也不断收到此错误phpinfo()

通过改变它:

memory_limit=4G

对此:

memory_limit=4096M

这纠正了 PHP 7 中的问题。

于 2017-03-13T11:26:16.090 回答
24

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

function exhaustYourBytes()
{
    return exhaustYourBytes();
}
于 2015-05-08T20:09:58.490 回答
22

您可以通过更改memory_limitfastcgi/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
于 2015-04-22T12:41:23.617 回答
21

您网站的根目录:

ini_set('memory_limit', '1024M');
于 2015-01-22T12:46:36.160 回答
19

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

; 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

于 2013-12-05T06:19:57.113 回答
14

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

$limit = ini_get('memory_limit');
ini_set('memory_limit', -1);
// ... do heavy stuff
ini_set('memory_limit', $limit);
于 2018-02-07T12:21:16.537 回答
13

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

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

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

于 2013-02-25T17:52:45.770 回答
13

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

您可以根据需要在 -1、to16M等位置设置内存。

于 2019-05-10T11:09:13.383 回答
12

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

memory_limit = -1

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

于 2018-06-26T05:20:19.900 回答
11

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

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

有效,但我们需要在开幕式之后放置

<?php

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

于 2012-12-06T17:48:48.603 回答
7

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

memory_limit = 64M

一些 cPanel 主机只接受这种方法。

于 2013-10-15T13:44:17.170 回答
7

崩溃页面?

在此处输入图像描述

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

您可以在增加之前检查系统现有内存状态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
于 2016-12-29T14:13:26.633 回答
6

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

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

class Proxy {

    private $actualObject;

    public function doSomething() {

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

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

于 2015-07-12T20:40:35.623 回答
6

在比以前工作的数据集更小的数据集上运行时,我遇到了以下错误。

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

由于寻找故障将我带到这里,我想我会提到它并不总是以前答案中的技术解决方案,而是更简单的东西。就我而言,它是 Firefox。在我运行该程序之前,它已经使用了 1,157 MB。

事实证明,在几天的时间里,我一次只看一段 50 分钟的视频,结果把事情搞砸了。这是专家在没有考虑的情况下纠正的那种修复,但对于我这样的人来说,这是值得牢记的。

于 2017-01-30T11:56:16.263 回答
3

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

而不是更改PHP.ini文件以获得更大的内存存储,有时实现yield内部循环可能会解决问题。yield 所做的不是一次转储所有数据,而是一一读取,节省大量内存使用。

于 2019-06-06T11:01:54.707 回答
2

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

在 WHM 11.48.4 上更新 memory_limit

于 2015-06-24T15:14:16.843 回答
2

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

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

于 2016-02-22T09:48:32.363 回答
2

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

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

于 2015-08-15T19:13:26.113 回答
2

在我的 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;"
于 2021-01-21T00:27:08.737 回答
1

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

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

在某些情况下,例如异常内的递归,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() 调用的行。

于 2019-07-16T15:37:45.860 回答
1

更改;memory_limit=512M;memory_limit=-1 _ 在此处输入图像描述

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

于 2020-09-13T08:50:40.457 回答
0

就我而言,它本身就是一个完整的磁盘和mysql shat。

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

一些路过的孩子设法淹没了我的日志并填满了我留在虚拟机上的稀缺的 500 多字节。:D

于 2021-09-08T15:48:29.667 回答
0

我花了两个时间寻找解决方案,我发现这是我打电话时与 PDO 通话的原因

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

变量周期是

empty string ''

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

更新:我使用 $pdo->query() 方法也遇到了这个错误我使用了 $pdo->prepare() 并且运行良好,所以,虽然我有

$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)); 

神奇地内存错误消失了!

于 2020-11-11T02:11:15.783 回答
0

这个问题是几年前问的,所以虽然我的事实不一样,但我最近在循环解析服务器上的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 行的结束连接符号。

于 2021-05-01T11:35:31.773 回答
0

就我而言,这是编写函数方式的一个简短问题。为函数的输入变量分配新值可能会导致内存泄漏,例如:

/**
* 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';
}
于 2019-03-18T14:55:51.487 回答
-7

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

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

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

于 2015-02-11T08:13:22.983 回答