Что значит "zend_mm_heap поврежден"
Внезапно у меня возникли проблемы с моим заявлением, которых у меня никогда не было раньше. Я решил проверить журнал ошибок Apache и обнаружил сообщение об ошибке "zend_mm_heap поврежден". Что это значит.
ОС: Fedora Core 8 Apache: 2.2.9 PHP: 5.2.6
41 ответ
После долгих проб и ошибок я обнаружил, что если я увеличу output_buffering
значение в файле php.ini, эта ошибка исчезает
Это не проблема, которая обязательно решается путем изменения параметров конфигурации.
Изменение параметров конфигурации иногда оказывает положительное влияние, но оно может так же легко ухудшить ситуацию или вообще ничего не делать.
Природа ошибки такова:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
void **mem = malloc(sizeof(char)*3);
void *ptr;
/* read past end */
ptr = (char*) mem[5];
/* write past end */
memcpy(mem[5], "whatever", sizeof("whatever"));
/* free invalid pointer */
free((void*) mem[3]);
return 0;
}
Код выше может быть скомпилирован с:
gcc -g -o corrupt corrupt.c
Выполняя код с помощью valgrind, вы можете увидеть много ошибок памяти, завершающихся ошибкой сегментации:
krakjoe@fiji:/usr/src/php-src$ valgrind ./corrupt
==9749== Memcheck, a memory error detector
==9749== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==9749== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==9749== Command: ./corrupt
==9749==
==9749== Invalid read of size 8
==9749== at 0x4005F7: main (an.c:10)
==9749== Address 0x51fc068 is 24 bytes after a block of size 16 in arena "client"
==9749==
==9749== Invalid read of size 8
==9749== at 0x400607: main (an.c:13)
==9749== Address 0x51fc068 is 24 bytes after a block of size 16 in arena "client"
==9749==
==9749== Invalid write of size 2
==9749== at 0x4C2F7E3: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9749== by 0x40061B: main (an.c:13)
==9749== Address 0x50 is not stack'd, malloc'd or (recently) free'd
==9749==
==9749==
==9749== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==9749== Access not within mapped region at address 0x50
==9749== at 0x4C2F7E3: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9749== by 0x40061B: main (an.c:13)
==9749== If you believe this happened as a result of a stack
==9749== overflow in your program's main thread (unlikely but
==9749== possible), you can try to increase the size of the
==9749== main thread stack using the --main-stacksize= flag.
==9749== The main thread stack size used in this run was 8388608.
==9749==
==9749== HEAP SUMMARY:
==9749== in use at exit: 3 bytes in 1 blocks
==9749== total heap usage: 1 allocs, 0 frees, 3 bytes allocated
==9749==
==9749== LEAK SUMMARY:
==9749== definitely lost: 0 bytes in 0 blocks
==9749== indirectly lost: 0 bytes in 0 blocks
==9749== possibly lost: 0 bytes in 0 blocks
==9749== still reachable: 3 bytes in 1 blocks
==9749== suppressed: 0 bytes in 0 blocks
==9749== Rerun with --leak-check=full to see details of leaked memory
==9749==
==9749== For counts of detected and suppressed errors, rerun with: -v
==9749== ERROR SUMMARY: 4 errors from 3 contexts (suppressed: 0 from 0)
Segmentation fault
Если вы не знали, вы уже поняли, что mem
выделена ли куча памяти; Куча относится к области памяти, доступной программе во время выполнения, потому что программа явно запросила ее (в нашем случае это malloc).
Если вы поиграете с ужасным кодом, вы обнаружите, что не все эти явно неправильные операторы приводят к ошибке сегментации (фатальная ошибка завершения).
Я явно сделал эти ошибки в примере кода, но такие же виды ошибок очень легко случаются в управляемой памяти среде: например, если какой-то код неправильно поддерживает пересчет переменной (или другого символа), например если он свободен, это слишком рано, другой фрагмент кода может прочитать из уже свободной памяти, если он каким-то образом хранит неправильный адрес, другой фрагмент кода может записать в недействительную память, он может быть освобожден дважды...
Это не проблемы, которые могут быть отлажены в PHP, они абсолютно требуют внимания со стороны внутреннего разработчика.
Курс действий должен быть:
- Откройте отчет об ошибке на http://bugs.php.net/
- Если у вас есть segfault, попробуйте предоставить обратную трассировку
- Включите столько информации о конфигурации, сколько кажется уместным, в частности, если вы используете opcache, включают уровень оптимизации.
- Продолжайте проверять отчет об ошибках на наличие обновлений, может потребоваться дополнительная информация.
- Если у вас загружен opcache, отключите оптимизацию
- Я не использую opcache, это здорово, но известно, что некоторые из его оптимизаций вызывают ошибки.
- Если это не сработает, хотя ваш код может работать медленнее, попробуйте сначала выгрузить opcache.
- Если что-то из этого изменит или решит проблему, обновите сделанный вами отчет об ошибке.
- Отключите все ненужные расширения сразу.
- Начните включать все ваши расширения по отдельности, тщательно тестируя после каждого изменения конфигурации.
- Если вы найдете расширение проблемы, обновите ваш отчет об ошибке с дополнительной информацией.
- Прибыль.
Там может не быть никакой прибыли... Я сказал в начале, вы можете найти способ изменить ваши симптомы, путаясь с конфигурацией, но это очень удачно, и не поможет в следующий раз, когда у вас есть тот же самый zend_mm_heap corrupted
сообщение, есть только так много вариантов конфигурации.
Очень важно, что мы создаем отчеты об ошибках, когда мы находим ошибки, мы не можем предполагать, что следующий человек, который ударит по ошибке, сделает это... скорее всего, фактическое разрешение ни в коем случае не загадочное, если вы сделаете правильные люди знают о проблеме.
USE_ZEND_ALLOC
Если вы установите USE_ZEND_ALLOC=0
в среде это отключает собственный менеджер памяти Zend; Диспетчер памяти Zend гарантирует, что у каждого запроса есть своя куча, что вся память освобождается в конце запроса, и оптимизирована для выделения кусков памяти, точно подходящего размера для PHP.
Отключение этой функции приведет к отключению этих оптимизаций, и, что более важно, это, вероятно, приведет к утечкам памяти, поскольку существует множество кода расширения, который полагается на Zend MM для освобождения памяти для них в конце запроса (tut, tut).
Это также может скрывать симптомы, но системная куча может быть повреждена точно так же, как и куча Zend.
Это может показаться более терпимым или менее терпимым, но устранить причину проблемы невозможно.
Возможность его вообще отключить, в интересах внутренних разработчиков; Вы никогда не должны развертывать PHP с отключенным Zend MM.
Я получал ту же ошибку в PHP 5.5 и увеличение буферизации вывода не помогло. У меня тоже не было APC, так что проблема не в этом. Я наконец отследил его до opcache, мне просто пришлось отключить его из клика. Для этого были определенные настройки:
opcache.enable_cli=0
После переключения поврежденная ошибка zend_mm_heap ушла.
Если вы используете Linux, попробуйте это в командной строке
export USE_ZEND_ALLOC=0
Проверить unset()
s. Убедитесь, что вы не unset()
ссылки на $this
(или эквиваленты) в деструкторах и что unset()
s в деструкторах не приводят к тому, что счетчик ссылок на один и тот же объект падает до 0. Я провел некоторое исследование и обнаружил, что именно это обычно приводит к повреждению кучи.
Существует сообщение об ошибке в PHP о поврежденной ошибке zend_mm_heap. Смотрите комментарий [2011-08-31 07:49 UTC] f dot ardelian at gmail dot com
для примера о том, как воспроизвести его.
У меня такое ощущение, что все остальные "решения" (меняются php.ini
, скомпилировать PHP из исходного кода с меньшим количеством модулей и т. д.) просто скрыть проблему.
Для меня ни один из предыдущих ответов не работал, пока я не попробовал:
opcache.fast_shutdown=0
Кажется, это работает до сих пор.
Я использую PHP 5.6 с PHP-FPM и Apache proxy_fcgi, если это имеет значение...
В моем случае причиной этой ошибки стало то, что один из массивов становился очень большим. Я установил свой скрипт для сброса массива на каждой итерации, и это решило проблему.
В соответствии с трекером ошибок установите opcache.fast_shutdown=0
, Быстрое выключение использует менеджер памяти Zend для очистки своего беспорядка, это отключает это.
Я боролся с этим вопросом в течение недели. Это сработало для меня, или, по крайней мере, так кажется
В php.ini
внести эти изменения
report_memleaks = Off
report_zend_debug = 0
Моя установка
Linux ubuntu 2.6.32-30-generic-pae #59-Ubuntu SMP
with PHP Version 5.3.2-1ubuntu4.7
Это не сработало.
Поэтому я попытался использовать эталонный скрипт и попытался записать, где скрипт зависал. Я обнаружил, что непосредственно перед ошибкой был создан экземпляр объекта php, и для выполнения того, что должен был делать объект, потребовалось более 3 секунд, тогда как в предыдущих циклах это занимало максимум 0,4 секунды. Я проводил этот тест довольно много раз, и каждый раз один и тот же. Я подумал, что вместо того, чтобы каждый раз создавать новый объект (здесь есть длинный цикл), я должен использовать объект повторно. Я тестировал скрипт более десятка раз, и ошибки памяти исчезли!
Я не думаю, что здесь есть один ответ, поэтому я добавлю свой опыт. Я видел эту же ошибку и случайные ошибки httpd. Это был сервер cPanel. Симптом, о котором идет речь, состоял в том, что apache случайно сбросил соединение (данные не были получены в chrome, или соединение было сброшено в firefox). Они были на первый взгляд случайными - большую часть времени это работало, иногда - нет.
Когда я прибыл на сцену, буферизация вывода была выключена. Читая эту ветку, которая намекала на выходную буферизацию, я включил ее (=4096), чтобы посмотреть, что произойдет. В этот момент все они начали показывать ошибки. Хорошо, что теперь ошибка повторяется.
Я прошел и начал отключать расширения. Среди них eaccellerator, pdo, загрузчик ioncube и многое другое, что выглядело подозрительно, но никто не помог.
Наконец-то я обнаружил непослушное расширение PHP как "homeloader.so", которое выглядит как некий модуль cPanel-easy-installer. После удаления других проблем не возникало.
На этом примечании, похоже, это общее сообщение об ошибке, поэтому ваш milage будет меняться со всеми этими ответами, лучший способ действий, которые вы можете предпринять:
- Сделайте ошибку повторяемой (какие условия?) Каждый раз
- Найти общий фактор
- Выборочно отключите любые модули PHP, опции и т. Д. (Или, если вы спешите, отключите их все, чтобы увидеть, помогает ли это, а затем выборочно включите их, пока он снова не сломается)
- Если это не помогает, многие из этих ответов намекают на то, что это может быть код, выпущенный. Опять же, ключ в том, чтобы ошибка повторялась при каждом запросе, чтобы вы могли сузить ее. Если вы подозреваете, что часть кода делает это, еще раз, после того, как ошибка повторяется, просто удалите код, пока ошибка не прекратится. Как только он останавливается, вы знаете, что последний кусок кода, который вы удалили, был виновником.
В противном случае вы также можете попробовать что-то вроде:
- Обновление или перекомпиляция PHP. Надеюсь, что любая ошибка, вызывающая вашу проблему, исправлена.
- Переместите ваш код в другую (тестовую) среду. Если это решит проблему, что изменилось? варианты php.ini? Версия PHP? так далее...
Удачи.
У меня только что была эта проблема на сервере, которым я владею, и основной причиной был APC. Я закомментировал расширение "apc.so" в файле php.ini, перезагрузил Apache, и сайты снова заработали.
У меня была эта ошибка при использовании драйвера Mongo 2.2 для PHP:
$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField', 'yetAnotherField'));
^^ НЕ РАБОТАЕТ
$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField'));
$collection->ensureIndex(array('yetAnotherField'));
^^ РАБОТАЕТ! (?!)
Найдите любой модуль, который использует буферизацию, и выборочно отключите его.
Я использую PHP 5.3.5 на CentOS 4.8, и после этого я обнаружил, что eaccelerator требуется обновление.
На PHP 5.3, после долгих поисков, это решение, которое работает для меня:
Я отключил сборку мусора PHP для этой страницы, добавив:
<? gc_disable(); ?>
до конца проблемной страницы, которая заставила все ошибки исчезнуть.
Я думаю, что много причин может вызвать эту проблему. И в моем случае я называю 2 класса одинаковыми, и один попытается загрузить другой.
class A {} // in file a.php
class A // in file b.php
{
public function foo() { // load a.php }
}
И это вызывает эту проблему в моем случае.
(Использование фреймворка laravel, запуск php artisan db:seed в режиме реального времени)
Я перепробовал все выше и zend.enable_gc = 0
- единственный конфиг, который мне помог.
PHP 5.3.10-1ubuntu3.2 с Suhosin-Patch (cli) (сборка: 13 июня 2012 17:19:58)
Если вы используете черты, и черта загружается после класса (т.е. в случае автозагрузки), вам нужно загрузить черту заранее.
https://bugs.php.net/bug.php?id=62339
Примечание: эта ошибка очень и очень случайна; из-за его природы.
Для меня проблема заключалась в использовании pdo_mysql. Запрос вернул результаты 1960 года. Я попытался вернуть 1900 записей, и это работает. Так что проблема в pdo_mysql и слишком большом массиве. Я переписал запрос с оригинальным расширением MySQL, и он работал.
$link = mysql_connect('localhost', 'user', 'xxxx') or die(mysql_error());
mysql_select_db("db", $link);
Apache не сообщал ни о каких предыдущих ошибках.
zend_mm_heap corrupted
zend_mm_heap corrupted
zend_mm_heap corrupted
[Mon Jul 30 09:23:49 2012] [notice] child pid 8662 exit signal Segmentation fault (11)
[Mon Jul 30 09:23:50 2012] [notice] child pid 8663 exit signal Segmentation fault (11)
[Mon Jul 30 09:23:54 2012] [notice] child pid 8666 exit signal Segmentation fault (11)
[Mon Jul 30 09:23:55 2012] [notice] child pid 8670 exit signal Segmentation fault (11)
"zend_mm_heap поврежден" означает проблемы с управлением памятью. Может быть вызван любым модулем PHP. В моем случае установка APC отработана. Теоретически могут помочь и другие пакеты, такие как eAccelerator, XDebug и т. Д. Или, если у вас установлены такие модули, попробуйте отключить их.
Многие люди упоминают об отключении XDebug для решения этой проблемы. Очевидно, что во многих случаях это невозможно, так как для этого есть причина - отладка вашего кода.
У меня возникла та же проблема, и я заметил, что если я перестал прослушивать соединения XDebug в моей IDE (PhpStorm 2019.1 EAP), ошибка перестала возникать.
Фактическое исправление, для меня, было удаление любых существующих точек останова.
Вероятность того, что это допустимое исправление, заключается в том, что PhpStorm иногда не так хорош в удалении точек останова, которые больше не ссылаются на действительные строки кода после внешнего изменения файлов (например, git).
Изменить: нашел соответствующий отчет об ошибке в трекере проблем xdebug: https://bugs.xdebug.org/view.php?id=1647
Я пишу расширение PHP, а также столкнулся с этой проблемой. Когда я вызываю функцию extern со сложными параметрами из моего расширения, появляется эта ошибка.
Причина в том, что я не выделяю память для параметра (char *) в функции extern. Если вы пишете такое же расширение, пожалуйста, обратите на это внимание.
У меня была такая же проблема, и когда у меня был неправильный IP для session.save_path для сессий memcached. Изменение правильного IP-адреса решило проблему.
Проблема с zend_mm_heap испортила boggeld меня примерно на пару часов. Сначала я отключил и удалил memcached, попробовал некоторые настройки, упомянутые в ответах на этот вопрос, и после тестирования это показалось проблемой с настройками OPcache. Я отключил OPcache, и проблема исчезла. После этого я снова включил OPcache, и для меня
core notice: child pid exit signal Segmentation fault
и
zend_mm_heap corrupted
очевидно решены с изменениями в
/etc/php.d/10-opcache.ini
Я включил сюда измененные настройки; opcache.revalidate_freq=2 остается закомментированным, я не менял это значение.
opcache.enable=1
opcache.enable_cli=0
opcache.fast_shutdown=0
opcache.memory_consumption=1024
opcache.interned_strings_buffer=128
opcache.max_accelerated_files=60000
В моем случае; Apache не запускается из-за проблемы с zend_mm_heap. У самого Apache не было проблем; потому что отключение php;
sudo emacs /etc/apache2/mods-enabled/php7.2.load
прокомментировать строку
# LoadModule php7_module /usr/lib/apache2/modules/libphp7.2.so
заставить apache работать правильно. Итак, я знаю, что проблема была в php. У меня было установлено более одного php, т.е. php 7.2 и php 8. Мой сайт использовал php 7.2 (поэтому мне пришлось использовать php7.2). Индивидуально одиночный php не имел никаких проблем. Но установка другой (более поздней) версии каким-то образом меняет кое-что, что вызывает эту проблему с повреждением zend_mm_heap. Очистка и установка не решает.
Решение было в том, что я использовал неправильную версию php. Я отключал php8.0, тогда как я установил php8.1.
sudo a2dismod php8.0
Изменение php8.0 на php8.1 решило все
sudo a2dismod php8.1
Настройка
assert.active = 0
в php.ini мне помогло (отключил утверждения типа в php5UTF8
библиотека и zend_mm_heap corrupted
ушел)
Некоторые из советов, которые могут помочь кому-то
fedora 20, php 5.5.18
public function testRead() {
$ri = new MediaItemReader(self::getMongoColl('Media'));
foreach ($ri->dataReader(10) as $data) {
// ...
}
}
public function dataReader($numOfItems) {
$cursor = $this->getStorage()->find()->limit($numOfItems);
// here is the first place where "zend_mm_heap corrupted" error occurred
// var_dump() inside foreach-loop and generator
var_dump($cursor);
foreach ($cursor as $data) {
// ...
// and this is the second place where "zend_mm_heap corrupted" error occurred
$data['Geo'] = [
// try to access [0] index that is absent in ['Geo']
'lon' => $data['Geo'][0],
'lat' => $data['Geo'][1]
];
// ...
// Generator is used !!!
yield $data;
}
}
использование var_dummp() на самом деле не является ошибкой, оно было помещено только для отладки и будет удалено из производственного кода. Но реальное место, где произошел zend_mm_heap - это второе место.
Этот вариант уже был написан выше, но я хочу показать вам, как я воспроизвел эту ошибку.
Вкратце. Мне помогло:
opcache.fast_shutdown = 0
Моя прежняя конфигурация:
- Релиз CentOS 6.9 (окончательный)
- PHP 5.6.24 (fpm-fcgi) с Zend OPcache v7.0.6-dev
- Битрикс CMS
Шаг за шагом:
- Бежать
phpinfo()
- Найдите "OPcache" в выводе. Он должен быть включен. Если нет, то это решение вам точно не поможет.
- Выполнить
opcache_reset()
в любом месте (спасибо сообщение об ошибке, комментарий[2015-05-15 09:23 UTC] nax_hh at hotmail dot com
). Загрузите несколько страниц на свой сайт. Если виноват OPcache, то в логах nginx появится строка с текстом
104: сброс подключения одноранговым узлом
и в журналах php-fpm
zend_mm_heap поврежден
и на следующей строке
fpm_children_bury()
- Набор
opcache.fast_shutdown=0
(для меня в/etc/php.d/opcache.ini
файл) - Перезапустите php-fpm (например,
service php-fpm restart
) - Снова загрузите несколько страниц вашего сайта. Выполнить
opcache_reset()
и снова загрузите несколько страниц. Теперь ошибок быть не должно.
Кстати. На выходе
phpinfo()
, вы можете найти статистику OPcache, а затем оптимизировать параметры (например, увеличить лимит памяти). Хорошая инструкция по настройке opcache (русский язык, но можно использовать переводчик)
13 ноября 2014 года в PHP была исправлена ошибка:
Исправлена ошибка #68365 (поврежден zend_mm_heap после переполнения памяти в zend_hash_copy).
Это было обновлено в версиях 5.4.35, 5.5.19 и 5.6.3. В моем случае, когда я перешел с использования официального надежного пакета Ubuntu (5.5.9+dfsg-1ubuntu4.14) на версию 5.5.30, упакованную Ondrej Sury, проблема исчезла. Ни одно из других решений не работало для меня, и я не хотел отключать opcache или подавлять ошибки, так как это действительно вызывало ошибки (500 ответов).
Ubuntu 14.04 LTS:
export LANG=C.UTF-8 # May not be required on your system
add-apt-repository ondrej/php5
apt-get update
apt-get upgrade
Для меня это был RabbitMq с Xdebug в PHPStorm, поэтому> Настройки / Язык и фреймворки /PHP/Debug/Xdebug > снимите флажок "Может принимать внешние подключения".
У меня возникла эта проблема при локальной разработке при использовании встроенного сервера разработки docker и php с Craft CMS.
Мое решение заключалось в использовании Redis для сеансов Craft.
PHP 7.4