Bu, yapılandırma seçeneklerini değiştirerek mutlaka çözülebilecek bir sorun değildir.
Yapılandırma seçeneklerini değiştirmek bazen olumlu bir etkiye sahip olabilir, ancak aynı şekilde işleri daha da kötüleştirebilir veya hiçbir şey yapmayabilir.
Hatanın doğası şudur:
#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;
}
Yukarıdaki kod şu şekilde derlenebilir:
gcc -g -o corrupt corrupt.c
Kodun valgrind ile yürütülmesi, bir bölümleme hatasıyla sonuçlanan birçok bellek hatasını görebilirsiniz:
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
Eğer bilmiyorsanız, mem
bunun yığın ayrılmış bellek olduğunu zaten anlamışsınızdır ; Yığın, program açık bir şekilde istediğinden (bizim durumumuzda malloc ile) programın çalışma zamanında kullanabileceği bellek bölgesini ifade eder.
Eğer korkunç kodla oynarsanız, açıkça yanlış olan ifadelerin hepsinin bir bölümleme hatasıyla (ölümcül bir sonlandırma hatası) sonuçlanmadığını göreceksiniz.
Örnek kodda bu hataları açıkça yaptım, ancak bellek yönetimli bir ortamda aynı tür hatalar çok kolay oluyor: Örneğin bazı kodlar bir değişkenin (veya başka bir sembolün) refcount'unu doğru şekilde tutmuyorsa, çok erken serbest kalırsa, başka bir kod parçası zaten boş olan bellekten okuyabilir, adresi bir şekilde yanlış saklarsa, başka bir kod parçası geçersiz belleğe yazabilir, iki kez serbest bırakılabilir ...
Bunlar PHP'de hata ayıklanabilecek sorunlar değildir, kesinlikle bir dahili geliştiricinin dikkatini gerektirir.
Eylem süreci şöyle olmalıdır:
- Http://bugs.php.net adresinde bir hata raporu açın
- Segfault'unuz varsa, geri izleme sağlamaya çalışın
- Özellikle opcache kullanıyorsanız, uygun göründüğü kadar çok yapılandırma bilgisi ekleyin optimizasyon düzeyi.
- Güncellemeler için hata raporunu kontrol etmeye devam edin, daha fazla bilgi istenebilir.
- Opcache yüklediyseniz optimizasyonları devre dışı bırakın
- Opcache seçmiyorum, bu harika, ancak bazı optimizasyonlarının hatalara neden olduğu biliniyor.
- Bu işe yaramazsa, kodunuz daha yavaş olsa bile, önce opcache'yi kaldırmayı deneyin.
- Bunlardan herhangi biri sorunu değiştirir veya düzeltirse, yaptığınız hata raporunu güncelleyin.
- Tüm gereksiz uzantıları aynı anda devre dışı bırakın .
- Her yapılandırma değişikliğinden sonra kapsamlı bir test yaparak tüm uzantılarınızı ayrı ayrı etkinleştirmeye başlayın.
- Sorun uzantısını bulursanız, hata raporunuzu daha fazla bilgi ile güncelleyin.
- Kar.
Herhangi bir kar olmayabilir ... Başlangıçta, konfigürasyonla uğraşarak semptomlarınızı değiştirmenin bir yolunu bulabileceğinizi söyledim, ancak bu son derece isabetli ve bir dahaki sefere yardımcı olmuyor. aynı zend_mm_heap corrupted
mesaj, yalnızca çok fazla yapılandırma seçeneği vardır.
Hatalar bulduğumuzda hata raporları oluşturmamız gerçekten önemlidir, hatayı bulan bir sonraki kişinin bunu yapacağını varsayamayız ... büyük olasılıkla, gerçek çözüm hiçbir şekilde gizemli değildir, eğer doğru insanlar sorunun farkında.
USE_ZEND_ALLOC
Ortama ayarlarsanız USE_ZEND_ALLOC=0
, bu Zend'in kendi hafıza yöneticisini devre dışı bırakır; Zend'in bellek yöneticisi, her isteğin kendi yığınına sahip olmasını, bir isteğin sonunda tüm belleğin serbest bırakılmasını ve PHP için doğru boyutta bellek parçalarının tahsisi için optimize edilmesini sağlar.
Devre dışı bırakmak, bu optimizasyonları devre dışı bırakacaktır, daha da önemlisi, bir isteğin sonunda onlar için belleği boşaltmak için Zend MM'ye dayanan birçok uzantı kodu olduğundan büyük olasılıkla bellek sızıntıları yaratacaktır (tut, tut).
Semptomları da gizleyebilir , ancak sistem yığını, Zend'in yığınıyla tamamen aynı şekilde bozulabilir.
Daha hoşgörülü veya daha az hoşgörülü görünebilir, ancak sorunun temel nedenini çözemez, olamaz .
Tamamen devre dışı bırakma yeteneği, dahili geliştiricilerin yararınadır; Sen gerektiğini asla devre dışı Zend MM'li PHP dağıtın.
USE_ZEND_ALLOC=0
hata günlüğünde stacktrace almak Ve hata buldum/usr/sbin/httpd: corrupted double-linked list
ben dışında yorum öğrendim,opcache.fast_shutdown=1
benim için çalıştı.