【问题标题】:Why and how is my PHP memory being exhausted? [duplicate]为什么以及如何耗尽我的 PHP 内存? [复制]
【发布时间】:2014-01-12 13:57:38
【问题描述】:

我收到了错误

PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 33292313 bytes)

当我运行分页功能时,我不知道发生了什么和/或为什么会出现错误。

根据我在这里看到的其他问题,大多数人建议我更改 php.ini 文件中的内存限制。但是,我想知道为什么会发生此错误以及我可以做些什么来防止它会在未来发生。

从这个问题Meaning of "Fatal error: Allowed memory size of x bytes exhausted (tried to allocate y bytes)"? 我可以看到 php 脚本已经超出了分配的内存限制(呃!)但它并没有真正的帮助。

问题:

  • php 不就是一种与数据库交互的语言吗?那为什么它需要内存才能运行呢?
  • 什么原因导致错误?(我知道内存不够,但为什么内存用完这么多)
  • 我能做些什么来防止它再次发生

我的分页功能:

function Pagination( $connection, $num, $page, $view  ) {

    $view=$view;

    //Results per page
    $pagerows=10;

    //Tells us the last page number
    $last=ceil( $num/$pagerows );

    // Establish the $PaginationNav variable(used to navigate the paginated results)
    $PaginationNav = '';

    //Check how many pages of results there are
    //If there is more than 1 page
    if( $last != 1 ) {

        //Check if we are on page 1, if so we don't need the 'previous' link
        //We are on page one
        if( $page == 1 ) {

            //Adds the current page
            $PaginationNav .= $page;

            //Adds the next 3 pages to the pagination
            for( $i=$page+1;$i<$last;$i++ ) {
                $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
                if( $i > $page+4 ) {
                    break;
                }
            }

            $PaginationNav .= "...";

            //Adds the last page to the pagination
            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$last\">$last</a>";

            //Adds the next page button
            $next=$page + 1;

            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$next\">Next </a> ";
        } else {
            //we are not on page 1

            //Adds the previous button to pagination
            $previous=$page - 1;

            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$previous\">Previous</a>";

            //Adds the current page
            $PaginationNav .=$page;

            //Adds the left navigations
            for( $i = $page-4;$i=$page;$i++ ) {
                if( $i>0 ) {
                    $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
                }
            }

            //Adds the right navigations
            for( $i=$page;$i<$last;$i++ ) {
                $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
                if( $i > $page+4 ) {
                    break;
                }
            }

            //Adds the last page to the pagination
            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$last\">... $last</a>";

            //Adds the next page button
            $next=$page + 1;

            $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$next\">Next </a> ";
        }
    }

    //There is only one page
    if( $last == 1 ) {
        $PaginationNav .= $page;
    }

    return $PaginationNav;
}

对我看到的一个问题有评论指出,简单地增加内存限制并不能很好地替代良好的编码。我同意,并且我想将代码更改为更好,而不是简单地盲目增加内存。

P.S 我没有接受过正式的编程培训,我只是通过全身心地投入到编码中来学习,所以如果答案很明显,我很抱歉。

【问题讨论】:

  • $view = $view - 这条线的目的是什么?另外,错误在哪一行?

标签: php memory memory-management


【解决方案1】:

你有:

 for($i = $page-4;$i=$page;$i++)   // change to ==
 {
     if($i>0)
     {
         $PaginationNav .= "<a class='Pagination' href=\"$_SERVER[PHP_SELF]?view=$view&page=$i\">$i</a>";
     }
 }

您将 $page 分配给 $i=$page 中的 $i ,它每次都会返回 $page (可能是一个正数),这将导致 true 条件。改成==

【讨论】:

    【解决方案2】:

    当 galchen 发现时,您有一个不正确的 for 循环终止符,导致无限循环最终因内存不足而中断。增加内存限制不会解决这个问题。

    我想提供我对您的 Pagination 函数的重写。我还没有测试过,但我相信它会产生更一致的整体结果。

    function Pagination($connection,$num,$page,$view,$pagerows=10) {
        //Tells us the last page number
        $last = ceil($num/$pagerows);
        if( $last == 1) return $page;
    
        // Establish the $PaginationNav variable(used to navigate the paginated results)
        $PaginationNav = '';
    
        // Helper function to reduce repeated code - great if you want to change the link!
        $addpage = function($p,$custom="") use (&$PaginationNav) {
            $PaginationNav .= "<a class='Pagination' href='".$_SERVER['PHP_SELF']."?view=".$view."&page=".$i.">".($custom ? $custom : $i)."</a>";
        };
    
        //Check if we are on page 1, if so we don't need the 'previous' link
        if( $page != 1) {
            //Adds the previous button to pagination
            $addpage($page-1,"Previous");
        }
        if( $page > 4) {
            //Adds the first page to the pagination
            $addpage(1);
            $PaginationNav .= "...";
        }
        //Adds the left navigations
        for($i = max(1,$page-4); $i < $page; $i++) {
            $addpage($i);
        }
        //Adds the current page
        $PaginationNav .= $page;
        //Adds the right navigations
        for($i=$page; $i<$last && $i < $page+4; $i++) {
            $addpage($i);
        }
        if( $page < $last-4) {
            $PaginationNav .= "...";
            //Adds the last page to the pagination
            $addpage($last);
        }
        if( $page != $last) {
            //Adds the next page button
            $addpage($page+1,"Next");
        }
        return $PaginationNav;
    }
    

    【讨论】:

    • 嗨 Niet,我看过了,特别是 addpage 辅助函数,有一些我不明白的部分,特别是引用传递、使用关键字(闭包)和函数末尾的三元运算符。从我在谷歌搜索后在 SO 上阅读的内容来看,人们似乎建议不要使用按引用传递,而是按值传递(即在调用 addpage 函数后返回 $PaginationNav)。如果是这样,使用它有什么好处你的例子?另外,'use'关键字和最后的三元运算符有什么用?
    • 如果您不通过引用传递,则必须在其他任何地方执行$PaginationNav .= $addpage(1);。在我看来,这使它更简单。三元运算符是使用$custom 文本(用于下一个和上一个)或数字(如果没有给出自定义文本)。
    猜你喜欢
    • 2011-10-01
    • 2014-06-28
    • 2020-10-09
    • 2013-07-06
    • 2015-10-01
    • 2011-07-06
    • 2010-12-15
    • 1970-01-01
    相关资源
    最近更新 更多