Ini bukan masalah yang perlu dipecahkan dengan mengubah opsi konfigurasi.
Mengubah opsi konfigurasi kadang-kadang akan berdampak positif, tetapi bisa dengan mudah memperburuk keadaan, atau tidak melakukan apa-apa sama sekali.
Sifat kesalahannya adalah 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;
}
Kode di atas dapat dikompilasi dengan:
gcc -g -o corrupt corrupt.c
Menjalankan kode dengan valgrind Anda dapat melihat banyak kesalahan memori, yang berujung pada kesalahan segmentasi:
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
Jika Anda tidak tahu, Anda sudah tahu bahwa itu mem
adalah tumpukan memori yang dialokasikan; Tumpukan mengacu pada wilayah memori yang tersedia untuk program saat runtime, karena program secara eksplisit memintanya (dengan malloc dalam kasus kami).
Jika Anda bermain-main dengan kode mengerikan, Anda akan menemukan bahwa tidak semua pernyataan yang jelas salah menghasilkan kesalahan segmentasi (kesalahan penghentian fatal).
Saya secara eksplisit membuat kesalahan dalam kode contoh, tetapi jenis kesalahan yang sama terjadi dengan sangat mudah dalam lingkungan yang dikelola memori: Jika beberapa kode tidak mempertahankan refcount variabel (atau simbol lain) dengan cara yang benar, misalnya jika gratis itu terlalu dini, sepotong kode lain mungkin membaca dari memori yang sudah bebas, jika entah bagaimana menyimpan alamat yang salah, sepotong kode lain mungkin menulis ke memori yang tidak valid, mungkin bebas dua kali ...
Ini bukan masalah yang bisa didebug dalam PHP, mereka benar-benar membutuhkan perhatian pengembang internal.
Tindakan yang harus dilakukan adalah:
- Buka laporan bug di http://bugs.php.net
- Jika Anda memiliki segfault, cobalah untuk menyediakan backtrace
- Sertakan sebanyak mungkin informasi konfigurasi yang sesuai, khususnya, jika Anda menggunakan opcache termasuk level optimisasi.
- Terus periksa laporan bug untuk pembaruan, informasi lebih lanjut mungkin diminta.
- Jika opcache Anda dimuat, nonaktifkan optimisasi
- Saya tidak memilih opcache, itu bagus, tetapi beberapa optimasi itu diketahui menyebabkan kesalahan.
- Jika itu tidak berhasil, walaupun kode Anda mungkin lebih lambat, coba bongkar dulu opcache.
- Jika salah satu dari ini mengubah atau memperbaiki masalah, perbarui laporan bug yang Anda buat.
- Nonaktifkan semua ekstensi yang tidak perlu sekaligus.
- Mulailah untuk mengaktifkan semua ekstensi Anda secara individual, dengan saksama menguji setelah setiap perubahan konfigurasi.
- Jika Anda menemukan ekstensi masalah, perbarui laporan bug Anda dengan info lebih lanjut.
- Keuntungan.
Mungkin tidak ada untung ... Saya katakan di awal, Anda mungkin dapat menemukan cara untuk mengubah gejala Anda dengan mengacaukan konfigurasi, tetapi ini sangat memukul dan meleset, dan tidak membantu saat berikutnya Anda memiliki zend_mm_heap corrupted
pesan yang sama , hanya ada begitu banyak opsi konfigurasi.
Sangat penting bagi kami untuk membuat laporan bug ketika kami menemukan bug, kami tidak dapat berasumsi bahwa orang berikutnya yang memukul bug akan melakukannya ... lebih mungkin daripada tidak, resolusi sebenarnya sama sekali tidak misterius, jika Anda membuat orang yang tepat menyadari masalah tersebut.
USE_ZEND_ALLOC
Jika Anda mengatur USE_ZEND_ALLOC=0
di lingkungan, ini menonaktifkan manajer memori Zend sendiri; Manajer memori Zend memastikan bahwa setiap permintaan memiliki tumpukan itu sendiri, bahwa semua memori dikosongkan pada akhir permintaan, dan dioptimalkan untuk alokasi potongan memori dengan ukuran yang tepat untuk PHP.
Menonaktifkan itu akan menonaktifkan optimasi tersebut, yang lebih penting itu kemungkinan akan membuat kebocoran memori, karena ada banyak kode ekstensi yang bergantung pada Zend MM untuk membebaskan memori bagi mereka di akhir permintaan (tut, tut).
Mungkin juga menyembunyikan gejalanya, tetapi tumpukan sistem dapat rusak dengan cara yang persis sama dengan tumpukan Zend.
Mungkin tampaknya lebih toleran atau kurang toleran, tetapi memperbaiki akar penyebab masalah, itu tidak bisa .
Kemampuan untuk menonaktifkannya sama sekali, adalah untuk kepentingan pengembang internal; Anda tidak boleh menggunakan PHP dengan Zend MM dinonaktifkan.
USE_ZEND_ALLOC=0
mendapatkan stacktrace di log kesalahan dan menemukan bug/usr/sbin/httpd: corrupted double-linked list
, saya menemukan bahwa mengomentariopcache.fast_shutdown=1
bekerja untuk saya.