【问题标题】:Simple For-Loop results in memory exhausted error简单的 For-Loop 导致内存耗尽错误
【发布时间】:2018-07-06 09:02:51
【问题描述】:

在本地化问题上工作了4个多小时,我终于找到了导致以下错误的代码部分:

PHP 致命错误:允许的内存大小为 268435456 字节已用尽 (试图分配8388608字节)在

我正在从我的数据库中获取数据。该查询返回一个包含 33 个条目的数据数组(不是那么多......) 我用for循环遍历该数组以获得时间差并标记数组如果差异太大(简单的if-else)......这很难解释,但我想你明白我的意思看看我的代码......它非常简单:

for($i = 0; $i <= count($customerList); $i++) {

        $date1 = date_create($customerList[$i]["lastUpdate"]);
        $interval = date_diff($date1, $date2);

        $min=$interval->format('%i');
        $sec=$interval->format('%s');
        $hour=$interval->format('%h');
        $mon=$interval->format('%m');
        $day=$interval->format('%d');
        $year=$interval->format('%y');

        $date3 = date("H");

        if(($year > 0) || ($mon > 0) || ($day > 0)) {
            $customerList[$i]["flag"] = 1;
        }
        else {
            if($date3 >= 6 && $date3 <= 21) {
                if(($hour > 0) || ($min > 29)) {
                    $customerList[$i]["flag"] = 1;
                }
            }
        }
}

变量$date2在for循环之前定义,代码如下:

$date2 = date_create($lastUpdateTime["lastUpdate"]);

遗憾的是,我真的不明白这段代码是如何导致该错误的,因为在我看来,这不应该真正使用那么多内存......

我 100% 确定错误来自这个 for 循环,因为当我删除它时,错误就消失了。此外,当我将此 for 循环放在其他视图中时,它会导致相同的错误。

我通过增加PHP的最大内存限制解决了这个问题,但我仍然想知道这个for循环是如何导致这个问题的。

我非常感谢任何解释,因为我在互联网上没有找到任何东西......

哦,我将在此处添加查询,以便您可以看到我没有获取大量数据(该站点处理更大的查询没有任何问题...):

SELECT c.id, c.type, c.name, c.environment, cd.customer, MAX(cd.createdAt) AS lastUpdate FROM customerdata AS cd JOIN customers c ON cd.customer = c.id GROUP BY customer ORDER BY c.name ASC

谢谢!

【问题讨论】:

  • 你应该在for($i = 0; $i &lt; count($customerList); $i++) 中只使用&lt;而不是&lt;=
  • 通过在 for 循环中使用 $i &lt;= count(..,您可以在循环内创建新的数组元素。这使得循环无限运行,每次创建一个新元素并在下一次迭代中处理它。您可以将for 循环替换为foreach,这样更易​​于阅读并防止出现此类错误。
  • 您也可以简单地将$interval-&gt;format() 调用替换为$interval-&gt;i, $interval-&gt;s, ... 就像现在一样,您正在获取存储在DateInterval 对象中的数字,格式化它们作为字符串,并将字符串转换回数字。
  • @KarstenKoop 非常感谢您对改进我的代码的帮助和建议:)

标签: php date for-loop


【解决方案1】:

您的for 循环条件是$i&lt;=count($customerList) 而不是$i&lt;count($customerList)。这意味着您对$customerList[$i] 的访问超过了数组的末尾,沿途创建了一个新元素。现在count($customerList) 变大了,因此循环进行了另一次迭代,无限循环,从而为不断增长的数组使用越来越多的 RAM。

当您阅读"lastUpdate" 时,您还应该在第一次访问它时收到一条警告消息,指出该元素不(尚)存在。稍后,当您设置 "flag" 元素时,您将创建数组元素。

为了使循环条件更易于阅读并防止出现此类拼写错误,您可以使用foreach 循环:

foreach ($customerList as $customer) {
    $date1 = date_create(customer["lastUpdate"]);
    $interval = date_diff($date1, $date2);
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 2023-03-05
    • 1970-01-01
    • 2011-05-06
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多