Что означает "куча Zend mm повреждена"

внезапно у меня возникли проблемы с моим приложением, что у меня никогда не было. Я решил проверить журнал ошибок Apache, и я нашел сообщение об ошибке "zend_mm_heap поврежден". Что это значит.

ОС: Fedora Core 8 Apache: 2.2.9 PHP: 5.2.6

30 ответов


после многих проб и ошибок я обнаружил, что если я увеличу output_buffering значение в php.ini-файл, эта ошибка уходит


Я получал эту же ошибку в PHP 5.5 и увеличение буферизации вывода не помогло. Я не запускал APC, так что это не было проблемой. Я, наконец, отследил его до opcache, Я просто должен был отключить его от cli. Для этого была специальная настройка:

opcache.enable_cli=0

после переключения поврежденная ошибка zend_mm_heap исчезла.


Если вы находитесь в Linux box, попробуйте это в командной строке

export USE_ZEND_ALLOC=0

это не проблема, обязательно разрешима путем изменения параметров конфигурации.

Изменение параметров конфигурации иногда будет иметь положительное влияние, но он может так же легко сделать вещи хуже, или вообще ничего не делать.

природа ошибки такова:

#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, они абсолютно требуют внимания разработчика internals.

курс действий должен быть:

  1. открыть отчет об ошибке на http://bugs.php.net
    • если у вас есть segfault, попробуйте предоставить backtrace
    • включить столько информации о конфигурации, сколько кажется подходящим, в частности, если вы используете opcache включить уровень оптимизации.
    • продолжайте проверять отчет об ошибке на наличие обновлений, может потребоваться дополнительная информация.
  2. если у вас загружен opcache, отключите оптимизацию
    • я не придираюсь к opcache, это здорово, но некоторые из его оптимизаций, как известно, вызывают ошибки.
    • если это не работает, даже если ваш код может быть медленнее, попробуйте сначала выгрузить opcache.
    • если какие-либо из этих изменений или исправляет проблему, обновите отчет об ошибке вы сделали.
  3. отключить все ненужные расширения сразу.
    • начните включать все ваши расширения индивидуально, тщательно тестируя после каждого изменения конфигурации.
    • если вы нашли расширение проблемы, обновите отчет об ошибке с дополнительной информацией.
  4. прибыль.

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

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

USE_ZEND_ALLOC

если вы устанавливаете USE_ZEND_ALLOC=0 в среда, это отключает собственный менеджер памяти Zend; менеджер памяти Zend гарантирует, что каждый запрос имеет свою собственную кучу, что вся память свободна в конце запроса и оптимизирована для выделения кусков памяти только нужного размера для PHP.

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

он также может скрыть симптомы, но системная куча может быть повреждена точно так же, как куча Zend.

это может показаться более терпимым или менее терпимым, но исправить основную причину проблемы,он не может.

возможность отключить его вообще, в интересах разработчиков internals; вы должны никогда развернуть на PHP с Zend инвалидов мм.


проверить unset()s. Убедитесь, что вы не unset() ссылки $this (или эквиваленты) в деструкторах и что unset()s в деструкторах не приводит к тому, что счетчик ссылок на один и тот же объект падает до 0. Я провел некоторое исследование и обнаружил, что это обычно вызывает повреждение кучи.

есть PHP сообщение об ошибке о zend_mm_heap поврежден ошибка. См. комментарий [2011-08-31 07:49 UTC] f dot ardelian at gmail dot com для примера о том, как воспроизвести его.

у меня такое ощущение что все остальные " решения "(change php.ini, компиляция PHP из исходного кода с меньшим количеством модулей и т. д. просто спрячь проблему.


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


для меня ни один из предыдущих ответов не работал, пока я не попробовал:

opcache.fast_shutdown=0

что, кажется, работает до сих пор.

Я использую PHP 5.6 с PHP-FPM и Apache proxy_fcgi, если это имеет значение...


в багтрекер, набор opcache.fast_shutdown=0. Быстрое завершение работы использует Zend memory manager для очистки своего беспорядка, это отключает это.


я боролся с этой проблемой, в течение недели это сработало для меня, или, по крайней мере, так кажется

на 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 segfaults. Это был сервер cPanel. Симптом был бы Апач случайно сброс соединения (без данных, полученных в Chrome или соединение было сброшено в Firefox). Они казались случайными - большую часть времени это срабатывало, иногда нет.

когда я прибыл на сцену, буферизация вывода была выключена. Читая эту тему, что намекало на буферизация вывода, я включил его (=4096), чтобы посмотреть, что произойдет. В этот момент они все начал показывать ошибки. Хорошо,что ошибка теперь повторялась.

Я прошел и начал отключать расширения. Среди них eaccellerator, pdo, ionCube погрузчик, и много, что посмотрел подозрение, но никто не помог.

Я наконец нашел расширение PHP шалить как "homeloader.так", которая появится какая-то панель-простота установки модуля. После удаления я не испытывал никаких других проблем.

на этой ноте, похоже, это общее сообщение об ошибке, поэтому ваш milage будет отличаться от всех этих ответов, лучший курс действий, который вы можете предпринять:

  • сделать ошибку повторяемой (какие условия?) каждый раз
  • найти общий фактор
  • выборочно отключите любые модули PHP, параметры и т. д. (Или, если вы спешите, отключите их все, чтобы увидеть, если это помогает, затем выборочно повторно включить их, пока он снова не сломается)
  • если это не поможет, многие из этих ответов намекают, что это может быть освобожден код. Опять же, ключ должен сделать ошибку повторяемой запрос так что вы можете сузить его. Если вы подозреваете, что часть кода делает это, еще раз, после повторения ошибки, просто удалите код, пока ошибка не остановится. Как только он остановится, вы знаете, что последний кусок кода, который вы удалили, был виновный.

в противном случае все вышеперечисленное, вы также можете попробовать такие вещи, как:

  • обновление или перекомпиляция PHP. Надеюсь, что любая ошибка вызывает вашу проблему исправлена.
  • переместите код в другую (тестовую) среду. Если это исправит проблему, что изменится? РНР.параметры ini? Версия PHP? так далее...

удачи.


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

Я запускаю PHP 5.3.5 на CentOS 4.8, и после этого я обнаружил, что eaccelerator нуждается в обновлении.


У меня просто была эта проблема, а также на сервере, которым я владею, и основной причиной был APC. Я прокомментировал "apc.Итак " расширение в php.ini-файл, перезагрузка Apache, и сайты вернулись обратно.


Я пробовал все выше и zend.enable_gc = 0 - единственная настройка конфигурации, которая мне помогла.

PHP 5.3.10-1ubuntu3.2 с Сухосин-патчем (cli) (построенный: июнь 13 2012 17:19:58)


у меня была эта ошибка, используя драйвер 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, после поиска лота, это решение, которое сработало для меня:

Я отключена сборка PHP мусора для этой страницы, добавив:

<? gc_disable(); ?>

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

источник.


Я думаю, что много причин могут вызвать эту проблему. И в моем случае я называю 2 класса одним и тем же именем, и один попытается загрузить другой.

class A {} // in file a.php
class A // in file b.php
{
  public function foo() { // load a.php }
}

и это вызывает эту проблему в моем случае.

(используя Laravel framework, запуск php artisan db:seed в реальном времени)


У меня была такая же проблема, и когда у меня был неправильный IP для сеанса.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, а также сталкиваюсь с этой проблемой. Когда я вызываю функцию extern со сложными параметрами из моего расширения, эта ошибка появляется.

причина в том, что я не выделяю память для параметра (char *) в функции extern. Если вы пишете такое же расширение, пожалуйста, обратите внимание на это.


для меня это был ZendDebugger, который вызвал утечку памяти и вызвал сбой MemoryManager.

Я отключил его, и в настоящее время я ищу более новую версию. Если не найду, переключусь на xdebug...


потому что я никогда не находил решения для этого, я решил обновить свою среду лампы. Я пошел в Ubuntu 10.4 LTS с PHP 5.3.X. Это, кажется, остановило проблему для меня.


в моем случае, я забыл следующее в коде:

);

Я играл и забыл его в коде здесь и там - в некоторых местах я получил повреждение кучи, в некоторых случаях просто ошибка ol' seg:

[Wed Jun 08 17:23:21 2011] [notice] child pid 5720 exit signal Segmentation fault (11)

Я на mac 10.6.7 и xampp.


Я также заметил эту ошибку и SIGSEGV при запуске старого кода, который использует"&", чтобы явно принудительно ссылаться при запуске в PHP 5.2+.


задание

assert.active = 0 

в php.ini помог мне (он отключил утверждения типа в php5UTF8 библиотеки и zend_mm_heap corrupted ушел)


для меня проблема была разбита демоном memcached, так как PHP был настроен для хранения информации о сеансе в memcached. Он ел 100% cpu и вел себя странно. После перезапуска 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, - это второе место.


Я был в такой же ситуации здесь, ничего выше не помогло, и проверка более серьезно я нахожу свою проблему, она состоит в том, чтобы попытаться умереть(заголовок()) после отправки некоторого вывода в буфер, человек, который сделал это в коде забыл о ресурсах CakePHP и не сделал simples "return $this->redirect($url)".

пытаясь заново изобрести колодец, это была проблема.

Я надеюсь, что это связано помочь кому-то!