Неустранимая ошибка: допустимый размер памяти 134217728 байтов исчерпан (CodeIgniter + XML-RPC)

У меня есть куча систем клиентской точки продажи (POS), которые периодически отправляют новые данные о продажах в одну централизованную базу данных, которая хранит данные в одной большой базе данных для генерации отчетов.

Клиентский POS основан на PHPPOS, и я внедрил модуль, который использует стандартную библиотеку XML-RPC для отправки данных о продажах в службу. Серверная система построена на CodeIgniter и использует библиотеки XML-RPC и XML-RPCS для компонента webservice. Всякий раз, когда я отправляю много данных о продажах (всего лишь 50 строк из таблицы продаж и отдельных строк из sales_items, относящихся к каждому элементу в продаже), я получаю следующую ошибку:

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

128M - значение по умолчанию в php.ini, но я предполагаю, что это огромное количество сломать. На самом деле, я даже попытался установить это значение на 1024 М, и все, что он делает, занимает больше времени для выхода из системы.

Что касается шагов, которые я предпринял, я попытался отключить всю обработку на стороне сервера и сфальсифицировал его, чтобы возвращать консервированный ответ независимо от ввода. Однако я считаю, что проблема заключается в фактической отправке данных. Я даже попытался отключить максимальное время выполнения script для PHP, и он все еще не работает.

Ответ 1

Изменение memory_limit помощью ini_set('memory_limit', '-1'); это не правильное решение. Пожалуйста, не делай этого.

В вашем PHP-коде может быть утечка памяти, и вы говорите серверу просто использовать всю необходимую память. Вы бы не решили проблему вообще. Если вы проконтролируете свой сервер, вы увидите, что он теперь, вероятно, использует большую часть оперативной памяти и даже подключается к диску.

Вероятно, вам следует попытаться отследить код в вашем коде и исправить его.

Ответ 3

Правильный способ - отредактировать файл php.ini. Измените memory_limit на ваше значение желания.

Как и в случае с вашим вопросом, предел 128M (который является лимитом по умолчанию) превышен, поэтому в вашем коде есть что-то серьезное, так как это не должно сильно занять.

Если вы знаете, почему это так много, и вы хотите разрешить ему устанавливать memory_limit = 512M или выше, и вам должно быть хорошо.

Ответ 4

Выделение памяти для PHP может быть отрегулировано постоянно или временно.

Постоянно

Вы можете навсегда изменить распределение памяти PHP двумя способами.

Если у вас есть доступ к вашему файлу php.ini, вы можете отредактировать значение memory_limit по своему желаемому значению.

Если у вас нет доступа к вашему файлу php.ini (и ваш веб-хост его разрешает), вы можете переопределить выделение памяти через ваш файл .htaccess. Добавьте php_value memory_limit 128M (или любое другое ваше выделение).

Временный

Вы можете настроить распределение памяти на лету из PHP файла. У вас просто есть код ini_set('memory_limit', '128M'); (или любое другое ваше выделение). Вы можете удалить ограничение памяти (хотя ограничения на использование машины или экземпляра могут все еще применяться), установив значение в "-1".

Ответ 5

Очень легко получить утечки памяти в PHP script - особенно если вы используете абстракцию, такую ​​как ORM. Попробуйте использовать Xdebug для профилирования вашего script и узнайте, куда пошла память.

Ответ 6

Добавляя 22,5 миллиона записей в массив с помощью array_push, я продолжал получать фатальные ошибки "исчерпал память", около 20 миллионов записей, используя 4G в качестве ограничения памяти в файле php.ini. Чтобы исправить это, я добавил выражение

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

в верхней части файла. Сейчас все работает нормально. Я не знаю, есть ли у PHP утечка памяти. Это не моя работа, и мне все равно. Я просто должен сделать свою работу, и это сработало.

Программа очень проста:

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

Неустранимая ошибка указывает на строку 3, пока я не увеличил предел памяти, что устранило ошибку.

Ответ 7

Я продолжал получать эту ошибку, даже когда memory_limit установлен в php.ini, и значение правильно phpinfo() с помощью phpinfo().

Изменяя это от этого:

memory_limit=4G

К этому:

memory_limit=4096M

Это исправило проблему в PHP 7.

Ответ 8

Когда вы видите вышеупомянутую ошибку, особенно если значение (tried to allocate __ bytes) является низким значением, это может быть индикатор бесконечного цикла, как функция, которая сама вызывает вызов:

function exhaustYourBytes()
{
    return exhaustYourBytes();
}

Ответ 9

После включения этих двух строк он начал работать:

; 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

Ответ 10

Вы можете исправить это, изменив memory_limit в fastcgi/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

Ответ 11

Корневой каталог вашего сайта:

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

Ответ 12

Для пользователей Drupal этот ответ Криса Лейна:

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

работает, но мы должны поставить его сразу после открытия

<?php

в файле index.php в корневом каталоге вашего сайта.

Ответ 13

В Drupal 7 вы можете изменить ограничение памяти в файле settings.php, который находится в папке sites/default. Вокруг строки 260 вы увидите это:

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

Даже если ваши настройки php.ini достаточно высоки, вы не сможете использовать более 128 МБ, если это не указано в файле Drupal settings.php.

Ответ 14

Вместо изменения значения memory_limit в вашем файле php.ini, если в вашем коде есть часть, которая может использовать много памяти, вы можете удалить memory_limit до memory_limit этого раздела, а затем заменить его после.

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

Ответ 15

Измените ограничение памяти в файле php.ini и перезапустите Apache. После перезагрузки запустите phpinfo(); функция из любого файла PHP для подтверждения изменения memory_limit.

memory_limit = -1

Ограничение памяти -1 означает, что ограничение памяти не установлено. Это сейчас на максимуме.

Ответ 16

PHP 5.3+ позволяет вам изменить ограничение памяти, поместив файл .user.ini в папку public_html. Просто создайте указанный выше файл и введите в него следующую строку:

memory_limit = 64M

Некоторые хосты cPanel принимают этот метод только.

Ответ 17

Краш страница?

Enter image description here

(Это происходит, когда 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 ниже, а затем выполните service httpd restart для устранения проблемы с страницей сбоя.

# grep memory_limit /etc/php.ini
memory_limit = 512M

Ответ 18

Для тех, кто ломает голову, чтобы понять, почему эта маленькая функция должна вызывать утечку памяти, иногда по маленькой ошибке, функция начинает рекурсивно вызывать себя навсегда.

Например, прокси-класс с тем же именем для функции объекта, который собирается его прокси.

class Proxy {

    private $actualObject;

    public function doSomething() {

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

Иногда вы можете забыть привезти этого маленького члена фактического Objec, и, поскольку прокси-сервер на самом деле имеет метод doSomething, PHP не даст вам никакой ошибки, а для большого класса его можно скрыть от глаз на пару минут, чтобы выяснить, почему это утечка памяти.

Ответ 19

У меня была ошибка ниже при работе с набором данных, меньшим, чем работал ранее.

Неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан (попытка выделить 4096 байт) в C:\workspace\image_management.php в строке 173

Поскольку поиск ошибки привел меня сюда, я подумал, что упомяну, что это не всегда технические решения в предыдущих ответах, но что-то более простое. В моем случае это был Firefox. До того, как я запустил программу, она уже использовала 1157 МБ.

Оказывается, я смотрел 50-минутное видео немного в течение нескольких дней, и это все испортило. Это исправление, которое эксперты исправляют, даже не задумываясь об этом, но для таких, как я, это стоит иметь в виду.

Ответ 20

Если вы используете виртуальный частный сервер с поддержкой WHM, вы можете обнаружить, что у вас нет прав для прямого редактирования PHP.INI; система должна это сделать. В панели управления хостом WHM перейдите к Конфигурация службы → Редактор конфигурации PHP и измените memory_limit:

Updating memory_limit on WHM 11.48.4

Ответ 21

Я нахожу это полезным, если включить или требовать _dbconnection.php_ и _functions.php в файлы, которые фактически обрабатываются, а не включать в заголовок. Который входит в себя.

Так что, если ваш заголовок и нижний колонтитул включены, просто включите все ваши функциональные файлы, прежде чем заголовок включен.

Ответ 22

Запуск script, как это (пример cron, например): php5 /pathToScript/info.php создает ту же ошибку.

Правильный способ: php5 -cli /pathToScript/info.php

Ответ 23

Эта ошибка иногда вызывается ошибкой в коде PHP, которая вызывает рекурсии, включающие обработку исключений и, возможно, другие операции. К сожалению, я не смог создать крошечный пример.

В этих случаях, которые случались со мной несколько раз, set_time_limit завершается сбоем, и браузер пытается загрузить вывод PHP либо с бесконечным циклом, либо с сообщением о фатальной ошибке, которое является темой этого вопроса.

Уменьшая допустимый размер выделения путем добавления

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

ближе к началу вашего кода вы сможете предотвратить фатальную ошибку.

Тогда вы можете остаться с программой, которая завершается, но все еще трудно отлаживать.

На этом этапе вставьте BreakLoop() внутри вашей программы, чтобы получить контроль и выяснить, какой цикл или рекурсия в вашей программе вызывают проблему.

Определение BreakLoop следующее:

function BreakLoop($MaxRepetitions=500,$LoopSite="unspecified")
    {
    static $Sites=[];
    if ([email protected]$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().

Ответ 25

В моем случае это была небольшая проблема с тем, как была написана функция. Утечка памяти может быть вызвана назначением нового значения входной переменной функции, например:

/**
* 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';
}

Ответ 26

Использование yield может быть решением. См. Синтаксис генератора.

Вместо того, чтобы PHP.ini файл PHP.ini для увеличения объема памяти, иногда использование yield внутри цикла может решить эту проблему. То, что делает yield - вместо того, чтобы выгружать все данные сразу, он читает их один за другим, экономя много памяти.

Ответ 27

Просто добавьте ini_set('memory_limit', '-1'); линия в верхней части вашей веб-страницы.

И вы можете установить свою память в соответствии с вашими потребностями вместо -1, до 16M и т.д.

Ответ 28

Очистите кеш браузера и попробуйте. ошибка может быть связана с тем, что браузер пытается загрузить большой файл или поврежденный файл на сервер.

Ответ 29

Когда я удалил следующие строки из моего кода, все работало хорошо!

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

Эти строки были включены в каждый файл, который я запускал. При запуске файлов один за другим все работало нормально, но при запуске всех файлов вместе у меня возникла проблема утечки памяти. Каким-то образом "include_once" не включает вещи один раз, или я делаю что-то не так...