深度递归内存泄漏 - 取消了一个fopen资源?

时间:2011-11-26 12:11:27

标签: php memory-management memory-leaks recursion

我有一个递归函数来迭代超过11M的数据库记录,一次1000个。当它接近9M时它停了下来。当我在每1000条记录后显示get_memory_usage()时,我确认了我对内存问题的假设。

该功能的工作原理如下:

<?
get_data_block();

function get_data_block($id=0);
{
    //open a csv file for writing
    $packages_sorted_csv=fopen("./csv/packages_sorted.csv", "a");

    //get 1000 records and process them
    //$unsorted = array of 1000 records from database
    foreach($unsorted as $row);
    {
        $ct++;
        $id++;
        //$packages_sorted = array of processed data

        //write output
        fputcsv($packages_sorted_csv, $packages_sorted);
    }
    fclose($packages_sorted_csv);

    if($ct==1000)
    {
        unset($unsorted);
        echo 'Mem usage: '.memory_get_usage();
        get_data_block($id);    //call the function again
    }else{
        //finished
    }
}

?>

有没有人有关于如何使用递归函数释放所有资源的提示? ...或者有没有办法再次调用相同的函数,因此它本身不会被调用?

注意:

  • 我必须将块中的数据块化以释放繁忙的mysql服务器。
  • 我尝试取消设置不在全局范围内的每个已定义变量。
  • 我唯一不能解开的是fopen资源。
  • 每次迭代内存大小增加约400k。

2 个答案:

答案 0 :(得分:2)

根据您发布的代码,递归似乎不是正确的方法。

构建第二个函数并重新排列,以便您可以执行类似(伪代码)的操作:

while (!$done) {
  $id = get_data_block($id);
  $done = // determine if finished or not
}

即。从$id返回get_data_block,如果不再需要处理,则为其提供无效值。你不必担心这种堆叠的堆栈帧。

答案 1 :(得分:2)

一个好的编程语言应该识别尾递归并将其转换为隐式循环。

PHP显然没有,所以在某些时候你会得到堆栈溢出。尝试重写代码以改为使用循环,或者例如迭代的处理队列。