Внезапно у меня возникли проблемы с моим приложением, которых у меня никогда раньше не было. Я решил проверить журнал ошибок Apache и обнаружил сообщение об ошибке «zend_mm_heap поврежден». Что это значит.
ОС: Fedora Core 8 Apache: 2.2.9 PHP: 5.2.6
Внезапно у меня возникли проблемы с моим приложением, которых у меня никогда раньше не было. Я решил проверить журнал ошибок Apache и обнаружил сообщение об ошибке «zend_mm_heap поврежден». Что это значит.
ОС: Fedora Core 8 Apache: 2.2.9 PHP: 5.2.6
Ответы:
После долгих проб и ошибок я обнаружил, что если я увеличу 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, они абсолютно требуют внимания внутреннего разработчика.
Порядок действий должен быть:
Может быть, нет никакой прибыли ... Я сказал в начале, что вы можете найти способ изменить свои симптомы, возясь с конфигурацией, но это очень удачно и не поможет в следующий раз, когда у вас возникнет одно и то же zend_mm_heap corrupted
сообщение, существует только определенное количество вариантов конфигурации.
Очень важно, чтобы мы создавали отчеты об ошибках, когда мы находим ошибки, мы не можем предполагать, что следующий человек, который столкнется с ошибкой, сделает это ... скорее всего, фактическое разрешение никоим образом не загадочно, если вы сделаете нужные люди осведомлены о проблеме.
Если вы установите USE_ZEND_ALLOC=0
в среде, это отключает собственный менеджер памяти Zend; Менеджер памяти Zend гарантирует, что у каждого запроса есть своя куча, что вся память будет освобождена в конце запроса и оптимизирована для выделения кусков памяти только нужного размера для PHP.
Отключение его отключит эти оптимизации, что более важно, это, вероятно, приведет к утечкам памяти, поскольку существует много кода расширения, который полагается на Zend MM для освобождения памяти для них в конце запроса (tut, tut).
Он также может скрыть симптомы, но системная куча может быть повреждена точно так же, как и куча Zend.
Это может показаться более терпимым или менее терпимым, но устранить основную причину проблемы он не может .
Возможность его вообще отключить предназначена для внутренних разработчиков; Никогда не следует развертывать PHP с отключенным Zend MM.
Я получал ту же ошибку в PHP 5.5, и увеличение буферизации вывода не помогло. Я тоже не использовал APC, так что проблема была не в этом. Я наконец отследил это до opcache , мне просто пришлось отключить его из cli. Для этого была особая настройка:
opcache.enable_cli=0
После переключения ошибка поврежденного zend_mm_heap исчезла.
Если вы используете Linux, попробуйте это в командной строке
export USE_ZEND_ALLOC=0
/etc/apache2/envvars
если вы запускаете это на сервере ubuntu с установленными apache и php из ppas (apt). PHP 7.0-RC4 начал выдавать эту ошибку, когда я установил его из репозитория ondrej.
set 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 для устранения беспорядка, это отключает это.
Я не думаю, что здесь есть один ответ, поэтому добавлю свой опыт. Я видел ту же ошибку вместе со случайными ошибками httpd segfaults. Это был сервер cPanel. Рассматриваемый симптом заключался в том, что apache произвольно сбрасывал соединение (данные не получены в Chrome, или соединение было сброшено в firefox). Они казались случайными - в большинстве случаев это срабатывало, иногда - нет.
Когда я прибыл на сцену, буферизация вывода была ВЫКЛЮЧЕНА. Прочитав эту ветку, в которой говорилось о буферизации вывода, я включил ее (= 4096), чтобы посмотреть, что произойдет. На этом этапе все они начали показывать ошибки. Хорошо, что теперь ошибка повторялась.
Я прошел и начал отключать расширения. Среди них, eaccellerator, PDO, IonCube погрузчик, и много что посмотрел подозрение, но ни помогло.
Я наконец нашел непослушное расширение PHP как "homeloader.so", которое, похоже, является своего рода модулем cPanel-easy-installer. После удаления у меня не возникло других проблем.
В этой заметке, похоже, это общее сообщение об ошибке, поэтому ваш пробег будет зависеть от всех этих ответов, лучший способ действий, который вы можете предпринять:
Если все вышеперечисленное не удается, вы также можете попробовать:
Удачи.
Я боролся с этой проблемой в течение недели, это сработало для меня, или, по крайней мере, так кажется
В 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 секунды. Я проводил этот тест несколько раз, и каждый раз одно и то же. Я подумал, что вместо того, чтобы каждый раз создавать новый объект (здесь длинный цикл), я должен использовать объект повторно. Я тестировал скрипт уже более десятка раз, и ошибки памяти исчезли!
Найдите любой модуль, который использует буферизацию, и выборочно отключите его.
Я использую PHP 5.3.5 на CentOS 4.8, и после этого я обнаружил, что eaccelerator требует обновления.
У меня тоже была эта проблема на моем сервере, и основной причиной была 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'));
^^ РАБОТАЕТ! (?!)
foreach(selectCollection()->find()) { $arr = .. }
На 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 в реальном)
У меня была такая же проблема, и когда у меня был неправильный IP-адрес для session.save_path для сеансов memcached. Изменение его на правильный IP-адрес устранило проблему.
Если вы используете трейт и трейт загружается после класса (то есть в случае автозагрузки), вам нужно загрузить трейт заранее.
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 и т. Д. Или, если у вас установлены такие модули, попробуйте отключить их.
Я пишу расширение php и тоже сталкиваюсь с этой проблемой. Когда я вызываю внешнюю функцию со сложными параметрами из своего расширения, появляется эта ошибка.
Причина в том, что я не выделяю память для параметра (char *) во внешней функции. Если вы пишете такое же расширение, обратите на это внимание.
Для меня именно ZendDebugger вызвал утечку памяти и привел к сбою MemoryManager.
Я отключил его и сейчас ищу более новую версию. Если не найду, перейду на xdebug ...
В моем случае я забыл в коде следующее:
);
Я поигрался и кое-где забыл об этом в коде - в некоторых местах я получал повреждение кучи, в некоторых случаях просто простая ошибка сегмента:
[Ср, 8 июня, 17:23:21 2011] [уведомление] дочерний pid 5720 сигнал выхода Ошибка сегментации (11)
У меня Mac 10.6.7 и xampp.
Я также заметил эту ошибку и SIGSEGV при запуске старого кода, который использует '&' для явного принудительного использования ссылок при запуске в PHP 5.2+.
Для меня проблема заключалась в сбое демона memcached, поскольку PHP был настроен для хранения информации о сеансе в memcached. Он ел 100% процессор и вел себя странно. После перезапуска memcached проблема исчезла.
Поскольку ни один из других ответов не касался этого, у меня была эта проблема в php 5.4, когда я случайно запустил бесконечный цикл.
Некоторые советы, которые могут кому-то помочь
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, - это второе место.
У меня была такая же ситуация здесь, ничего из вышеперечисленного не помогло, и, более серьезно проверяя, я нахожу свою проблему, она состоит в том, что попробуйте do die (header ()) после отправки некоторого вывода в буфер, человек, который сделал это в коде, забыл о ресурсах CakePHP и не сделал простого "return $ this-> redirect ($ url)".
Проблема была в попытке заново изобрести колодец.
Я надеюсь, что это поможет кому-то!
USE_ZEND_ALLOC=0
получал трассировку стека в журнале ошибок и обнаружил ошибку/usr/sbin/httpd: corrupted double-linked list
, я обнаружил, что комментированиеopcache.fast_shutdown=1
сработало для меня.