Este no es un problema que necesariamente se puede resolver cambiando las opciones de configuración.
Cambiar las opciones de configuración a veces tendrá un impacto positivo, pero con la misma facilidad puede empeorar las cosas o no hacer nada.
La naturaleza del error es la siguiente:
#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;
}
El código anterior se puede compilar con:
gcc -g -o corrupt corrupt.c
Al ejecutar el código con valgrind, puede ver muchos errores de memoria, que culminan en un error de segmentación:
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 no lo sabía, ya descubrió que se mem
trata de memoria asignada en el montón; El montón se refiere a la región de memoria disponible para el programa en tiempo de ejecución, porque el programa lo solicitó explícitamente (con malloc en nuestro caso).
Si juegas con el código terrible, encontrarás que no todas esas declaraciones obviamente incorrectas resultan en una falla de segmentación (un error de terminación fatal).
Cometí explícitamente esos errores en el código de ejemplo, pero los mismos tipos de errores ocurren muy fácilmente en un entorno administrado por memoria: si algún código no mantiene el recuento de una variable (u otro símbolo) de la manera correcta, por ejemplo si lo libera demasiado pronto, puede leerse otro fragmento de código de la memoria ya liberada, si de alguna manera almacena la dirección incorrecta, otro fragmento de código puede escribir en una memoria no válida, puede liberarse dos veces ...
Estos no son problemas que se puedan depurar en PHP, requieren absolutamente la atención de un desarrollador interno.
El curso de acción debe ser:
- Abra un informe de error en http://bugs.php.net
- Si usted tiene un error de segmentación, trata de proporcionar una traza inversa
- Incluya toda la información de configuración que parezca apropiada, en particular, si está utilizando opcache, incluya el nivel de optimización.
- Siga revisando el informe de errores para obtener actualizaciones, se puede solicitar más información.
- Si tiene opcache cargado, deshabilite las optimizaciones
- No estoy eligiendo opcache, es genial, pero se sabe que algunas de sus optimizaciones causan fallas.
- Si eso no funciona, aunque su código sea más lento, primero intente descargar opcache.
- Si algo de esto cambia o soluciona el problema, actualice el informe de error que realizó.
- Deshabilite todas las extensiones innecesarias a la vez.
- Comience a habilitar todas sus extensiones individualmente, realizando pruebas exhaustivas después de cada cambio de configuración.
- Si encuentra la extensión del problema, actualice su informe de errores con más información.
- Lucro.
Puede que no haya ningún beneficio ... Dije al principio, es posible que pueda encontrar una manera de cambiar sus síntomas jugando con la configuración, pero esto es extremadamente impredecible y no ayuda la próxima vez que tenga el mismo zend_mm_heap corrupted
mensaje, solo hay muchas opciones de configuración.
Es realmente importante que creemos informes de errores cuando los encontremos, no podemos suponer que la próxima persona que lo haga lo hará ... lo más probable es que la resolución real no sea misteriosa, si usted hace el personas adecuadas conscientes del problema.
USE_ZEND_ALLOC
Si configura USE_ZEND_ALLOC=0
en el entorno, esto desactiva el propio administrador de memoria de Zend; El administrador de memoria de Zend garantiza que cada solicitud tenga su propio montón, que toda la memoria se libere al final de una solicitud y que esté optimizada para la asignación de fragmentos de memoria del tamaño adecuado para PHP.
Deshabilitarlo deshabilitará esas optimizaciones, lo que es más importante, probablemente creará pérdidas de memoria, ya que hay una gran cantidad de código de extensión que depende del Zend MM para liberar memoria al final de una solicitud (tut, tut).
También puede ocultar los síntomas, pero el montón del sistema se puede dañar exactamente de la misma manera que el montón de Zend.
Puede parecer que ser más tolerantes o menos tolerantes, pero solucionar la causa raíz del problema, no se puede .
La capacidad de deshabilitarlo es para beneficio de los desarrolladores internos; Usted debe nunca se desplegará PHP con Zend MM desactivado.
USE_ZEND_ALLOC=0
obtener el stacktrace en el registro de errores y encontré el error/usr/sbin/httpd: corrupted double-linked list
, descubrí que comentarloopcache.fast_shutdown=1
funcionó para mí.