web-dev-qa-db-fra.com

Que signifie "zend_mm_heap corrompu"

Tout à coup, j'ai eu des problèmes avec ma candidature que je n'avais jamais eu auparavant. J'ai décidé de vérifier le journal des erreurs d'Apache et j'ai trouvé un message d'erreur disant "zend_mm_heap corrompu". Qu'est-ce que ça veut dire.

Système d'exploitation: Fedora Core 8 Apache: 2.2.9 PHP: 5.2.6

115
bkulyk

Après de nombreux essais et erreurs, j'ai constaté que si j'augmentais la valeur output_buffering dans le fichier php.ini, cette erreur disparaîtrait.

50
dsmithers

J'obtenais cette même erreur sous PHP 5.5 et l'augmentation de la mise en mémoire tampon de la sortie n'a pas aidé. Je n'utilisais pas non plus APC, alors ce n'était pas le problème. Je l'ai finalement retrouvé dans opcache , je devais simplement le désactiver depuis la cli. Il y avait un paramètre spécifique pour cela: 

opcache.enable_cli=0

Une fois commuté, l'erreur corrompue zend_mm_heap est partie. 

44
Justin MacLeod

Si vous êtes sous Linux, essayez ceci en ligne de commande 

export USE_ZEND_ALLOC=0
40
Hittz

Ce problème ne peut pas nécessairement être résolu en modifiant les options de configuration. 

Changer les options de configuration aura parfois un impact positif, mais cela peut tout aussi bien aggraver les choses ou ne rien faire du tout.

La nature de l'erreur est la suivante:

#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;
}

Le code ci-dessus peut être compilé avec:

gcc -g -o corrupt corrupt.c

En exécutant le code avec valgrind, vous pouvez voir de nombreuses erreurs de mémoire, aboutissant à une erreur de segmentation:

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

Si vous ne le saviez pas, vous avez déjà compris que mem est de la mémoire allouée par tas. Le tas fait référence à la région de mémoire disponible pour le programme à l'exécution, parce que le programme l'a explicitement demandé (avec malloc dans notre cas).

Si vous jouez avec ce code épouvantable, vous constaterez que toutes ces déclarations manifestement incorrectes ne donnent pas nécessairement lieu à une erreur de segmentation (une erreur de terminaison fatale).

J'ai explicitement fait ces erreurs dans l'exemple de code, mais le même type d'erreur se produit très facilement dans un environnement géré en mémoire: Si un code ne gère pas correctement le nombre de références d'une variable (ou d'un autre symbole), par exemple, si c'est gratuit trop tôt, un autre morceau de code peut lire dans la mémoire déjà libre, s'il enregistre l'adresse erronée, un autre morceau de code peut écrire dans une mémoire invalide, il peut être libre deux fois ...

Ce ne sont pas des problèmes qui peuvent être débogués en PHP, ils nécessitent absolument l’attention d’un développeur interne.

La marche à suivre devrait être:

  1. Ouvrez un rapport de bogue sur http://bugs.php.net
    • Si vous avez une erreur de segmentation, essayez de fournir un backtrace
    • Incluez autant d'informations de configuration que cela semble approprié, en particulier si vous utilisez le niveau d'optimisation opcache include.
    • Continuez à vérifier le rapport de bogue pour les mises à jour, plus d'informations peuvent être demandées.
  2. Si vous avez chargé opcache, désactivez les optimisations
    • Je ne choisis pas opcache, c'est génial, mais certaines de ses optimisations sont connues pour causer des erreurs.
    • Si cela ne fonctionne pas, même si votre code est plus lent, essayez tout d’abord de décharger opcache.
    • Si cela change ou corrige le problème, mettez à jour le rapport de bogue que vous avez rédigé.
  3. Désactivez tous extensions inutiles à la fois .
    • Commencez à activer toutes vos extensions individuellement et effectuez des tests approfondis après chaque modification de configuration.
    • Si vous trouvez l'extension du problème, mettez à jour votre rapport de bogue avec plus d'informations.
  4. Profit.

Il n'y aura peut-être aucun profit ... J'ai dit au début que vous pourriez peut-être trouver un moyen de changer vos symptômes en jouant avec la configuration, mais c'est extrêmement aléatoire et cela n'aide pas la prochaine fois. le même message zend_mm_heap corrupted, il n’existe que peu d’options de configuration.

Il est vraiment important de créer des rapports de bogues lorsque nous trouvons des bogues, nous ne pouvons pas supposer que la prochaine personne à le toucher le fera ... plus probablement qu'autrement, la résolution réelle n'est nullement mystérieuse, si vous faites le les bonnes personnes conscientes du problème.

USE_ZEND_ALLOC

Si vous définissez USE_ZEND_ALLOC=0 dans l'environnement, cela désactive le propre gestionnaire de mémoire de Zend; Le gestionnaire de mémoire de Zend garantit que chaque requête a son propre tas, que toute la mémoire est libre à la fin d'une requête et optimisée pour l'allocation de blocs de mémoire de la taille idéale pour PHP.

Si vous le désactivez, cela désactivera ces optimisations. Plus important encore, cela créera probablement des fuites de mémoire, car de nombreux codes d’extension reposent sur Zend MM pour libérer de la mémoire à la fin d’une requête (tut, tut).

Il peut aussi masquer les symptômes, mais le tas système peut être corrompu de la même manière que le tas de Zend. 

Il peut sembler être plus tolérant ou moins tolérant, mais corrigez la cause première du problème, il ne peut pas.

La possibilité de le désactiver est à l’avantage des développeurs internes; Vous devriez ne jamais déployer PHP avec Zend MM désactivé.

34
Joe Watkins

Vérifiez pour unset()s. Assurez-vous de ne pas faire référence à unset() au $this (ou à son équivalent) dans les destructeurs et à ce que unset()s dans les destructeurs n'entraîne pas la réduction à 0 du compte de référence du même objet. la corruption du tas.

Il y a un rapport de bogue PHP concernant le zend_mm_heap corrompu error. Voir le commentaire [2011-08-31 07:49 UTC] f dot ardelian at gmail dot com pour un exemple sur la façon de le reproduire.

J'ai l'impression que toutes les autres "solutions" (modifier le php.ini, compiler PHP à partir du source avec moins de modules, etc.) masquent simplement le problème.

23
f.ardelian

Dans mon cas, la cause de cette erreur était que l’un des tableaux devenait très gros. J'ai configuré mon script pour réinitialiser le tableau à chaque itération et cela a réglé le problème. 

7
Piotr

Selon le traqueur de bogues, définissez opcache.fast_shutdown=0. L'arrêt rapide utilise le gestionnaire de mémoire Zend pour nettoyer ses dégâts, cela désactive cela.

5
Taco de Wolff

Pour moi, aucune des réponses précédentes n'a fonctionné, jusqu'à ce que j'essaye:

opcache.fast_shutdown=0

Cela semble fonctionner jusqu'à présent. 

J'utilise PHP 5.6 avec PHP-FPM et Apache proxy_fcgi, si cela compte ...

5
Jesús Carrera

J'ai lutté avec cette question, pendant une semaine, cela a fonctionné pour moi, ou du moins il semble 

Dans php.ini apporter ces modifications 

report_memleaks = Off  
report_zend_debug = 0  

Mon montage est 

Linux ubuntu 2.6.32-30-generic-pae #59-Ubuntu SMP  
with PHP Version 5.3.2-1ubuntu4.7  

Cela n'a pas fonctionné. 

Alors j'ai essayé d'utiliser un script de référence, et essayé d'enregistrer où le script était suspendu . J'ai découvert que juste avant l'erreur, un objet php était instancié, et qu'il fallait plus de 3 secondes pour terminer ce que l'objet était supposé faire, alors que dans les boucles précédentes cela prenait max 0.4 secondes. J'ai couru ce test plusieurs fois et à chaque fois. J'ai pensé qu'au lieu de créer un nouvel objet à chaque fois (il y a une longue boucle ici), je devrais réutiliser l'objet. J'ai testé le script plus d'une douzaine de fois jusqu'à présent et les erreurs de mémoire ont disparu!

4
sam

Je ne pense pas qu'il y ait une seule réponse ici, alors je vais ajouter mon expérience. J'ai vu cette même erreur avec des segfaults httpd aléatoires. C'était un serveur cPanel. Le symptôme en question était qu'Apache réinitialiserait la connexion de manière aléatoire (aucune donnée reçue en chrome, ou la connexion a été réinitialisée dans Firefox). Celles-ci étaient apparemment aléatoires - la plupart du temps, cela fonctionnait, parfois non.

Quand je suis arrivé sur la scène, la mise en mémoire tampon était désactivée. En lisant ce fil, qui faisait allusion à la mise en mémoire tampon de la sortie, je l’ai activé (= 4096) pour voir ce qui se produirait. À ce stade, ils ont tous commencé à afficher les erreurs. C'était bien d'être que l'erreur était maintenant répétable.

J'ai traversé et commencé à désactiver les extensions. Parmi eux, eaccellerator, pdo, ioncube loader, et beaucoup de ce qui a regardé la suspicion, mais aucun n'a aidé.

J'ai finalement trouvé l'extension PHP coquine sous le nom "homeloader.so", qui semble être une sorte de module cPanel-easy-installer. Après le retrait, je n'ai rencontré aucun autre problème.

Sur cette note, il semble qu'il s'agisse d'un message d'erreur générique. Votre kilométrage variera donc avec toutes ces réponses. Le meilleur plan d'action que vous puissiez prendre est le suivant:

  • Rendre l'erreur répétable (quelles conditions?) À chaque fois
  • Trouver le facteur commun
  • Désactivez sélectivement les PHP modules, options, etc. (ou, si vous êtes pressé, désactivez-les tous pour voir si cela aide, puis réactivez-les de manière sélective jusqu'à ce qu'il se bloque à nouveau)
  • Si cela ne résout pas le problème, bon nombre de ces réponses suggèrent que le code pourrait être répété. Encore une fois, la clé est de rendre l'erreur répétable chaque requête afin de pouvoir la réduire. Si vous pensez qu'un morceau de code est en train de le faire, encore une fois, une fois que l'erreur est répétable, supprimez simplement le code jusqu'à ce que l'erreur s'arrête. Une fois que cela s’arrête, vous savez que le dernier morceau de code que vous avez supprimé est le coupable.

À défaut de tout ce qui précède, vous pouvez également essayer des solutions telles que:

  • Mettre à jour ou recompiler PHP. J'espère que le bug causant votre problème est corrigé.
  • Déplacez votre code dans un environnement (de test) différent. Si cela résout le problème, qu'est-ce qui a changé? Options php.ini? PHP version? etc...

Bonne chance.

3
A.B. Carroll

Recherchez tout module utilisant la mise en mémoire tampon et désactivez-le sélectivement.

J'utilise PHP 5.3.5 sur CentOS 4.8, et après cela, j'ai découvert eaccelerator qui avait besoin d'une mise à niveau.

2
Scott Davey

Je viens d’avoir ce problème également sur un serveur que je possède, et la cause première était APC. J'ai commenté l'extension "apc.so" dans le fichier php.ini, j'ai rechargé Apache et les sites sont remontés.

2
Vance Lucas

Sur PHP 5.3, après de nombreuses recherches, voici la solution qui a fonctionné pour moi:

J'ai désactivé la corbeille PHP pour cette page en ajoutant:

<? gc_disable(); ?>

à la fin de la page problématique, qui a fait disparaître toutes les erreurs. 

la source .

2
Kuf

Je pense que beaucoup de raisons peuvent causer ce problème. Et dans mon cas, je nomme 2 classes du même nom, et on essaiera d'en charger une autre. 

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

Et cela cause ce problème dans mon cas.

(Utilisation du framework laravel, exécution de php artisan db: seed in real)

2
Yarco

J'ai eu cette erreur en utilisant le pilote Mongo 2.2 pour PHP:

$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField', 'yetAnotherField')); 

^^ NE FONCTIONNE PAS

$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField')); 
$collection->ensureIndex(array('yetAnotherField')); 

^^ FONCTIONNE! (?!)

2
hernanc

J'ai tout essayé ci-dessus et zend.enable_gc = 0 - le seul paramètre de configuration qui m'a aidé.

PHP 5.3.10-1ubuntu3.2 avec Suhosin-Patch (cli) (construit: 13 juin 2012 17:19:58) 

2
Bethrezen

J'écris une extension php et rencontre aussi ce problème. Lorsque j'appelle une fonction externe avec des paramètres compliqués de mon extension, cette erreur se produit. 

La raison en est que je n'alloue pas de mémoire pour un paramètre (char *) dans la fonction externe. Si vous écrivez le même type d'extension, veuillez faire attention à cela.

1
cedricliang

Si vous utilisez des traits et que le trait est chargé après la classe (c'est-à-dire le cas du chargement automatique), vous devez le charger au préalable.

https://bugs.php.net/bug.php?id=62339

Note: ce bug est très très aléatoire; en raison de sa nature. 

1
srcspider

Pour moi, le problème était d'utiliser pdo_mysql. La requête a renvoyé 1960 résultats. J'ai essayé de retourner 1900 enregistrements et cela fonctionne. Donc, le problème est pdo_mysql et un tableau trop grand. J'ai réécrit la requête avec l'extension mysql originale et cela a fonctionné.

$link = mysql_connect('localhost', 'user', 'xxxx') or die(mysql_error());
mysql_select_db("db", $link);

Apache n'a signalé aucune erreur précédente. 

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)
1
broadband

J'ai eu ce même problème et quand j'avais une adresse IP incorrecte pour session.save_path pour les sessions memcached. Le changer à l'adresse IP correcte a résolu le problème. 

1
Travis Derouin

"zend_mm_heap corrompu" signifie des problèmes de gestion de la mémoire. Peut être causé par n'importe quel module PHP . Dans mon cas, l'installation d'APC a fonctionné. En théorie, d'autres packages tels que eAccelerator, XDebug, etc. peuvent également aider. Ou, si vous avez installé ce type de modules, essayez de les désactiver.

1
Muto

Beaucoup de gens mentionnent la désactivation de XDebug pour résoudre le problème. Cela n'est évidemment pas viable dans de nombreux cas, car il est activé pour une raison: déboguer votre code.

J'avais le même problème et j'ai remarqué que si j'arrêtais d'écouter les connexions XDebug dans mon IDE (PhpStorm 2019.1 EAP), l'erreur cessait de se produire.

Pour moi, la solution consistait à supprimer les points d'arrêt existants.

Une possibilité pour que ce soit un correctif valide est que PhpStorm n'est parfois pas très efficace pour supprimer les points d'arrêt qui ne référencent plus les lignes de code valides après la modification externe des fichiers (par exemple, par git).

Edit: Trouvé le rapport de bogue correspondant dans le suivi des problèmes de xdebug: https://bugs.xdebug.org/view.php?id=1647

0
Dejan Lukić

Avait zend_mm_heap corrupted avec child pid ... exit signal Segmentation fault sur un serveur Debian mis à niveau vers jessie. Après de longues recherches, il s’est avéré que XCache avait été installé avant que Zend-Engine ne soit généralement disponible.

après apt-get remove php5-xcache et service Apache2 restart, les erreurs ont disparu.

0
Martin Seitl

Quelques conseils qui peuvent aider quelqu'un

Fedora 20, 5.5.18 php

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;
    }
}

en utilisant var_dummp (), ce n’est pas une erreur, il a été placé uniquement pour le débogage et sera supprimé du code de production. Mais le lieu réel où zend_mm_heap s'est passé est la deuxième place. 

0
lexand

J'étais dans la même situation ici, rien de ce qui précède n'a aidé, et en vérifiant plus sérieusement je trouve mon problème, il consiste à essayer de faire die (header) après l'envoi d'une sortie au tampon, l'homme qui l'a fait dans le Code a oublié les ressources de CakePHP et n'a pas fait un simple "return $ this-> redirect ($ url)".

Essayer de réinventer le puits, c’était le problème.

J'espère que cette relation aide quelqu'un!

Pour moi, c'était RabbitMq avec Xdebug dans PHPStorm, donc> Paramètres/Langage et structures/PHP/Debug/Xdebug> décochez "Peut accepter les connexions externes".

0
Sébastien Grans

Puisqu'aucune des autres réponses ne l'a abordé, j'ai eu ce problème dans PHP 5.4 lorsque j'ai accidentellement exécuté une boucle infinie.

0
Trenton Maki

Pour moi, c’est le ZendDebugger qui a provoqué la fuite de mémoire et provoqué le blocage de MemoryManager.

Je l'ai désactivé et je suis actuellement à la recherche d'une version plus récente. Si je ne peux pas en trouver un, je vais passer à xdebug ...

0
Structed

Même si quelqu'un d'autre a ce problème de la même manière que moi, j'ai pensé proposer la solution qui me convenait le mieux.

J'ai installé php sur Windows sur un lecteur autre que le lecteur système ( H: ). 

Dans mon fichier php.ini, la valeur de plusieurs variables de système de fichiers différentes était écrite comme \path\to\directory - ce qui aurait bien fonctionné si mon installation était sur C:.

Je devais changer la valeur en H:\path\to\directory. L'ajout de la lettre de lecteur à plusieurs endroits différents dans mon fichier php.ini a résolu le problème immédiatement. Je me suis également assuré (bien que je ne pense pas que cela soit nécessaire) de résoudre le même problème dans mon PEAR config - car plusieurs valeurs de variable excluaient également la lettre de lecteur.

0
dgo

Un bogue avait été corrigé dans PHP le 13 novembre 2014:

Correction du bug # 68365 (zend_mm_heap corrompu après un débordement de mémoire dans zend_hash_copy).

Cela a été mis à jour dans les versions 5.4.35, 5.5.19 et 5.6.3. Dans mon cas, lorsque j'ai cessé d'utiliser le paquetage officiel officiel d'Ubuntu (5.5.9 + dfsg-1ubuntu4.14) en version 5.5.30 fournie par Ondrej Sury, le problème a disparu. Aucune des autres solutions ne fonctionnait pour moi et je ne voulais pas désactiver opcache ou supprimer les erreurs car cela causait réellement des erreurs de segmentation (500 réponses).

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
0
ColinM

Beaucoup de réponses ici sont anciennes. Pour moi (php 7.0.10 via le PPA d'Ondrej Sury sur Ubuntu 14.04 et 16.04), le problème semble se situer à APC. Je mettais en cache des centaines de petits morceaux de données en utilisant apc_fetch (), etc., et en invalidant une partie du cache, j'obtenais l'erreur. La solution consistait à basculer vers la mise en cache basée sur un système de fichiers.

Plus de détails sur github https://github.com/oerdnj/deb.sury.org/issues/452#issuecomment-245475283

0
Steve

Pour moi, le problème venait du blocage du démon memcached, car PHP était configuré pour stocker les informations de session dans memcached. Il mangeait 100% de cpu et agissait bizarrement. Après que le problème de redémarrage de Memcached soit résolu.

0
Justinas Jaronis

Dans mon cas, j'ai oublié de suivre dans le code:

)

J'ai joué et oublié dans le code ici et là - à certains endroits, j'ai eu la corruption du tas, certains cas tout simplement une faute grave:

 [Mer 08 juin 17:23:21 2011] [avis] pid enfant 5720 signal de sortie Défaillance Segmentation (11).

Je suis sur mac 10.6.7 et xampp.

0
dsomnus

J'ai également remarqué cette erreur et les erreurs SIGSEGV lors de l'exécution d'un ancien code qui utilise '&' pour forcer explicitement les références lors de son exécution dans PHP 5.2+.

0
Phillip Whelan

N'ayant jamais trouvé de solution à ce problème, j'ai décidé de mettre à niveau mon environnement LAMP. Je suis allé à Ubuntu 10.4 LTS avec PHP 5.3.x. Cela semble avoir arrêté le problème pour moi.

0
bkulyk

Réglage 

assert.active = 0 

dans php.ini m'a aidé (il a désactivé les assertions de type dans la bibliothèque php5UTF8 et que zend_mm_heap corrupted est parti)

0
Vasiliy

Vraiment traquer votre code pour une erreur silencieuse. Dans mon application Symfony, l'erreur zend_mm_heap a été corrompue après la suppression d'un bloc d'un modèle de base de brindille ne rappelant pas qu'il était référencé dans des sous-modèles. Aucune erreur n'a été lancée.

0
hipnosis