Dies ist kein Problem, das unbedingt durch Ändern der Konfigurationsoptionen gelöst werden kann.
Das Ändern von Konfigurationsoptionen wirkt sich manchmal positiv aus, kann aber genauso gut die Situation verschlimmern oder gar nichts bewirken.
Die Art des Fehlers ist folgende:
#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;
}
Der obige Code kann kompiliert werden mit:
gcc -g -o corrupt corrupt.c
Wenn Sie den Code mit valgrind ausführen, werden viele Speicherfehler angezeigt, die in einem Segmentierungsfehler gipfeln:
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
Wenn Sie es nicht wussten, haben Sie bereits herausgefunden, dass dem mem
Heap Speicher zugewiesen ist. Der Heap bezieht sich auf den Speicherbereich, der dem Programm zur Laufzeit zur Verfügung steht, da das Programm dies explizit angefordert hat (in unserem Fall mit malloc).
Wenn Sie mit dem schrecklichen Code herumspielen, werden Sie feststellen, dass nicht alle dieser offensichtlich falschen Anweisungen zu einem Segmentierungsfehler führen (ein schwerwiegender Beendigungsfehler).
Ich habe diese Fehler explizit im Beispielcode gemacht, aber die gleichen Arten von Fehlern treten in einer speicherverwalteten Umgebung sehr leicht auf: Wenn ein Code beispielsweise die Nachzählung einer Variablen (oder eines anderen Symbols) nicht auf die richtige Weise beibehält Wenn es zu früh freigegeben wird, kann ein anderes Stück Code aus dem bereits freigegebenen Speicher gelesen werden. Wenn es die falsche Adresse irgendwie speichert, kann ein anderes Stück Code in einen ungültigen Speicher schreiben, es kann zweimal freigegeben werden ...
Dies sind keine Probleme, die in PHP behoben werden können. Sie erfordern unbedingt die Aufmerksamkeit eines internen Entwicklers.
Die Vorgehensweise sollte sein:
- Öffnen Sie einen Fehlerbericht auf http://bugs.php.net
- Wenn Sie eine segfault haben, versuchen , eine schaffen Backtrace
- Fügen Sie so viele Konfigurationsinformationen ein, wie angemessen erscheint, insbesondere wenn Sie die Optimierungsstufe für Opcache-Include verwenden.
- Überprüfen Sie den Fehlerbericht weiterhin auf Aktualisierungen. Möglicherweise werden weitere Informationen angefordert.
- Wenn Sie Opcache geladen haben, deaktivieren Sie Optimierungen
- Ich wähle keinen Opcache aus, es ist großartig, aber es ist bekannt, dass einige seiner Optimierungen Fehler verursachen.
- Wenn dies nicht funktioniert, obwohl Ihr Code möglicherweise langsamer ist, versuchen Sie zuerst, den Opcache zu entladen.
- Wenn dies das Problem ändert oder behebt, aktualisieren Sie den von Ihnen erstellten Fehlerbericht.
- Deaktivieren Sie alle unnötigen Erweiterungen gleichzeitig.
- Aktivieren Sie alle Ihre Erweiterungen einzeln und testen Sie sie nach jeder Konfigurationsänderung gründlich.
- Wenn Sie die Problemerweiterung finden, aktualisieren Sie Ihren Fehlerbericht mit weiteren Informationen.
- Profitieren.
Es kann sein, dass es keinen Gewinn gibt ... Ich sagte zu Beginn, dass Sie möglicherweise einen Weg finden können, Ihre Symptome zu ändern, indem Sie mit der Konfiguration herumspielen, aber dies ist ein großer Erfolg und Misserfolg und hilft beim nächsten Mal nicht weiter die gleiche zend_mm_heap corrupted
Meldung, es gibt nur so viele Konfigurationsmöglichkeiten.
Es ist wirklich wichtig, dass wir Fehlerberichte erstellen, wenn wir Fehler finden. Wir können nicht davon ausgehen, dass die nächste Person, die den Fehler entdeckt, dies tun wird. Wahrscheinlich ist die tatsächliche Lösung in keiner Weise mysteriös, wenn Sie die Fehler beheben richtige Leute, die sich des Problems bewusst sind.
USE_ZEND_ALLOC
Wenn Sie USE_ZEND_ALLOC=0
in der Umgebung festlegen , wird der eigene Speichermanager von Zend deaktiviert. Der Speichermanager von Zend stellt sicher, dass jede Anforderung einen eigenen Heap hat, dass der gesamte Speicher am Ende einer Anforderung frei ist und für die Zuweisung von Speicherblöcken optimiert ist, die genau die richtige Größe für PHP haben.
Durch Deaktivieren werden diese Optimierungen deaktiviert, was noch wichtiger ist, es wird wahrscheinlich zu Speicherlecks kommen, da es viele Erweiterungscodes gibt, die darauf beruhen, dass das Zend MM am Ende einer Anforderung (tut, tut) Speicher für sie freigibt.
Es kann auch die Symptome verbergen , aber der System-Heap kann genauso beschädigt werden wie der Zend-Heap.
Es mag toleranter oder weniger tolerant erscheinen, aber die Hauptursache des Problems kann nicht behoben werden .
Die Möglichkeit, es überhaupt zu deaktivieren, kommt den internen Entwicklern zugute. Sie sollten PHP niemals mit deaktiviertem Zend MM bereitstellen.
USE_ZEND_ALLOC=0
die Stapelverfolgung im Fehlerprotokoll abgerufen und den Fehler gefunden/usr/sbin/httpd: corrupted double-linked list
. Ich habe herausgefunden, dass das Auskommentierenopcache.fast_shutdown=1
für mich funktioniert hat.