неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан (codeigniter + xml-rpc)

<p>у меня есть система клиентских точек продаж (pos), которые периодически отправляют новые данные о продажах в одну централизованную базу данных, которая хранит данные в одной большой базе данных для генерации отчетов.</p><p>pos клиента основан на phppos, и я реализовал модуль, который использует стандартную библиотеку xml-rpc для отправки данных о продажах в сервис. серверная система построена на codeigniter и использует библиотеки xml-rpc и xml-rpcs для компонента веб-сервиса. всякий раз, когда я отправляю много данных о продажах (всего 50 строк из таблицы продаж и отдельные строки из sales\_items, относящиеся к каждому товару в продаже), я получаю следующую ошибку:</p><pre><code>fatal error: allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes) </code></pre><p>128m является значением по умолчанию в <code>php.ini</code>, но я предполагаю, что это огромное число, которое нужно сломать. на самом деле, я даже пытался установить это значение равным 1024m, и все, что он делает, это занимает больше времени, чтобы выдать ошибку.</p><p>что касается шагов, которые я предпринял, я попытался отключить всю обработку на стороне сервера и настроил ее так, чтобы она возвращала стандартный ответ независимо от входных данных. тем не менее, я считаю, что проблема заключается в фактической отправке данных. я даже пытался отключить максимальное время выполнения скрипта для php, и он все еще выдает ошибки.</p>

<p>изменение <code>memory\_limit</code> на <code>ini\_set('memory\_limit', '-1');</code> является <strong>не</strong> правильным решением. пожалуйста, не делай этого.</p><p>ваш код php может где-то иметь утечку памяти, и вы говорите серверу просто использовать всю необходимую память. вы бы не решили проблему вообще. если вы проконтролируете свой сервер, вы увидите, что он теперь, вероятно, использует большую часть ram и даже выгружается на диск.</p><p>вероятно, вам следует попытаться отследить код в вашем коде и исправить его.</p>

<p><code>ini\_set('memory\_limit', '-1');</code> переопределяет значение по умолчанию <a href="http://php.net/memory\_limit">ограничение памяти php</a> .</p>

<p>правильный способ - отредактировать ваш файл <code>php.ini</code>. отредактируйте <code>memory\_limit</code> по своему желанию.</p><p>как видно из вашего вопроса, <code>128m</code> (который является пределом по умолчанию) был превышен, поэтому в вашем коде что-то серьезно не так, поскольку это не должно занимать так много времени.</p><p>если вы знаете, почему это занимает так много времени, и вы хотите, чтобы он установил <code>memory\_limit = 512m</code> или выше, у вас все должно получиться.</p>

<p>выделение памяти для php может быть изменено постоянно или временно.</p><h2>постоянно</h2><p>вы можете навсегда изменить выделение памяти php двумя способами.</p><p>если у вас есть доступ к файлу <code>php.ini</code>, вы можете отредактировать значение для <code>memory\_limit</code> по своему желанию.</p><p>если у вас нет доступа к вашему файлу <code>php.ini</code> (и ваш веб-хост позволяет это), вы можете переопределить распределение памяти через файл <code>.htaccess</code>. добавьте <code>php\_value memory\_limit 128m</code> (или как хотите).</p><h2>временный</h2><p>вы можете настроить распределение памяти на лету из файла php. у вас просто есть код <code>ini\_set('memory\_limit', '128m');</code> (или что-то еще, что вы хотите). вы можете удалить ограничение памяти (хотя ограничения машины или экземпляра все еще могут применяться), установив значение "-1".</p>

<p>утечки памяти в скрипте php очень легко - особенно если вы используете абстракцию, такую как orm. попробуйте использовать xdebug для профилирования вашего скрипта и выяснить, куда ушла вся эта память.</p>

<p>добавляя 22,5 миллиона записей в массив с помощью array\_push, я продолжал получать фатальные ошибки "исчерпал память", около 20 миллионов записей, используя 4g в качестве предела памяти в php.ini. чтобы исправить это я добавил заявление</p><pre><code>$old = ini_set('memory_limit', '8192m'); в верхней части файла. сейчас все работает нормально. я не знаю, есть ли у php утечка памяти, это не моя работа, и мне все равно. я просто должен сделать свою работу, и это сработало.программа очень проста:$fh = fopen($myfile); while (!feof($fh)) { array\_push($file, stripslashes(fgets($fh))); } fclose($fh); неустранимая ошибка указывает на строку 3, пока я не увеличил предел памяти, что устранило ошибку.

я продолжал получать эту ошибку, даже с memory_limit, установленным в php.ini, и значением, считываемым правильно с phpinfo().изменяя это от этого:memory_limit=4g к этому:memory_limit=4096m это исправило проблему в php 7.

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

после включения этих двух строк. это начало работать; 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 <img src="https://content.screencast.com/users/pkmauyra/folders/jing/media/8afa91fd-d7da-4e62-86f4-571e457e1bf9/2013-12-05_1120.png" alt="">

вы можете исправить это, изменив memory_limit на fastcgi/fpm$vim /etc/php5/fpm/php.ini </code></pre><p>поменяйте память как со 128 на 512 см ниже</p><pre><code>; maximum amount of memory a script may consume (128mb) ; http://php.net/memory-limit memory\_limit = 128m </code></pre><p>в</p><pre><code>; maximum amount of memory a script may consume (128mb) ; http://php.net/memory-limit memory\_limit = 512m </code></pre>

<p><strong>корневой каталог вашего сайта: -</strong></p><pre><code>ini\_set('memory\_limit', '1024m'); </code></pre>

<p>измените ограничение памяти из файла <strong>php.ini</strong> и перезапустите apache. после перезапуска запустите функцию <strong>phpinfo ();</strong> из любого php-файла для подтверждения изменения memory\_limit.</p><pre><code>memory\_limit = -1 </code></pre><p>ограничение памяти -1 означает, что ограничение памяти не установлено, теперь оно максимально.</p>

<p>вместо изменения значения <code>memory\_limit</code> в вашем файле <code>php.ini</code>, если есть часть вашего кода, которая может использовать много памяти, вы можете удалить <code>memory\_limit</code> до запуска этого раздела, а затем заменить его после.</p><pre><code>$limit = ini_get('memory_limit'); ini_set('memory_limit', -1); // ... do heavy stuff ini_set('memory_limit', $limit); </code></pre>

<p>в drupal 7 вы можете изменить ограничение памяти в файле settings.php, который находится в папке sites/default. вокруг строки 260 вы увидите это:</p><pre><code>ini\_set('memory\_limit', '128m'); </code></pre><p>даже если ваши настройки php.ini достаточно высоки, вы не сможете использовать больше 128 мб, если это не установлено в вашем файле drupal settings.php.</p>

<p>для drupal пользователей этот ответ криса лейна:</p><pre><code>ini\_set('memory\_limit', '-1'); </code></pre><p>работает, но мы должны поставить его сразу после открытия</p><pre><code><?php </code></pre><p>тег в файле index.php в корневом каталоге вашего сайта.</p>

<p>php 5.3+ позволяет изменить ограничение памяти, поместив файл <code>.user.ini</code> в папку <code>public\_html</code>. просто создайте файл выше и введите в нем следующую строку:<br></p><pre><code>memory\_limit = 64m </code></pre><p>некоторые хосты cpanel принимают только этот метод.</p>

<p><strong> crash-страница? </strong> <a href="https://i.stack.imgur.com/a2iym.png"><img src="https://i.stack.imgur.com/a2iym.png" alt="enter image description here"></a> </p><p>(это происходит, когда mysql должен запрашивать большие строки, по умолчанию для momory\_limit установлено значение small, что было более безопасно для оборудования)</p><p>вы можете проверить состояние вашей системы в памяти, прежде чем увеличивать <code>php.ini</code></p><pre><code># free -m total used free shared buffers cached mem: 64457 63791 666 0 1118 18273 -/+ buffers/cache: 44398 20058 swap: 1021 0 1021 </code></pre><p>здесь я увеличил его следующим образом, а затем <code>service httpd restart</code>, чтобы исправить проблему crash page.</p><pre><code># grep memory\_limit /etc/php.ini memory\_limit = 512m </code></pre>

<p>для тех, кто царапает свои волосы, чтобы понять, почему в земле эта маленькая функция должна вызывать утечку памяти, иногда по маленькой ошибке, функция начинает рекурсивно вызывать себя навсегда.<br></p><p>например, прокси-класс с тем же именем для функции объекта, который собирается его прокси.</p><pre><code>class proxy { private $actualobject; public function dosomething() { return $this->actualobjec->dosomething(); } } </code></pre><p>иногда вы можете забыть привезти этот маленький член actualobjec, и поскольку у proxy действительно есть метод dosomething, php не даст вам никакой ошибки, а для большого класса он может быть скрыт от глаз для пары минут, чтобы выяснить, почему это утечка памяти.</p>

<p>у меня была ошибка ниже при работе с набором данных, меньшим, чем работал ранее.</p><pre><code>fatal error: allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) in c:\\workspace\image\_management.php on line 173 </code></pre><p>поскольку поиск ошибки привел меня сюда, я подумал, что упомяну, что это не всегда технические решения, описанные выше, а что-то более простое. в моем случае это был firefox. до того, как я запустил программу, она уже использовала 1,157m.<br> оказывается, я немного смотрел 50-минутное видео за несколько дней, и это все испортило. это исправление, которое эксперты исправляют, даже не задумываясь об этом, но для таких, как я, это стоит иметь в виду.</p>

<p>если вы используете виртуальный частный сервер на базе whm, вы можете обнаружить, что у вас нет прав для прямого редактирования php.ini; система должна это сделать. на панели управления хоста whm выберите конфигурация службы> php редактор конфигурации, измените memory\_limit:</p><p><img src="https://i.stack.imgur.com/kewys.png" alt="updating memory\_limit on whm 11.48.4"></p>

<p>запуск сценария следующим образом (например, cron): <code>php5 /pathtoscript/info.php</code> выдает ту же ошибку.</p><p>правильный путь: <code>php5 -cli /pathtoscript/info.php</code></p>

<p>я считаю это полезным, если включить или требовать:<br> <em> dbconnection.php </em>, \_functions.php в файлах, которые фактически обрабатываются,<br> , а не в заголовке. который включен сам.</p><p>поэтому, если ваши <strong>header</strong> и <strong>footer</strong> включены, просто включите все ваши функциональные файлы перед включением заголовка.</p>

<p>использование <code>yield</code> также может быть решением <a href="https://www.php.net/manual/en/language.generators.syntax.php">https://www.php.net/manual/en/language.generators.syntax.php</a> </p><p>вместо изменения файла <code>php.ini</code> для увеличения объема памяти, иногда реализация <code>yield</code> внутри цикла может решить проблему. то, что делает yield - вместо того, чтобы выкидывать все данные за раз, он читает по одному, экономя много памяти.</p>

<p>в моем случае это была небольшая проблема с тем, как была написана функция. утечка памяти может быть вызвана назначением нового значения входной переменной функции, например:</p><pre><code>/** * memory leak function that illustrates unintentional bad code * @param $variable - input function that will be assigned new value  @return null / function dosomehting($variable){ $variable = 'set value'; // or $variable .= 'set value'; } </code></pre>

<p>просто добавьте ini\_set ('memory\_limit', '-1'); линия в верхней части вашей веб-страницы. и вы можете установить свою память в соответствии с вашими потребностями в месте от -1 до 16m и т.д.</p>