갑자기 내가 전에는 본 적이없는 응용 프로그램에 문제가있었습니다. Apache의 오류 로그를 확인하기로 결정한 후 "zend_mm_heap 손상됨"이라는 오류 메시지를 발견했습니다. 이것은 무엇을 의미 하는가.
운영체제 : Fedora Core 8 Apache : 2.2.9 PHP : 5.2.6
갑자기 내가 전에는 본 적이없는 응용 프로그램에 문제가있었습니다. Apache의 오류 로그를 확인하기로 결정한 후 "zend_mm_heap 손상됨"이라는 오류 메시지를 발견했습니다. 이것은 무엇을 의미 하는가.
운영체제 : Fedora Core 8 Apache : 2.2.9 PHP : 5.2.6
답변:
많은 시행 착오 끝에 output_buffering
php.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;
}
위의 코드는 다음과 같이 컴파일 할 수 있습니다.
gcc -g -o corrupt corrupt.c
valgrind로 코드를 실행하면 세분화 오류로 인해 많은 메모리 오류를 볼 수 있습니다.
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
모르는 경우 이미 mem
힙 할당 메모리 임을 알았습니다 . 힙은 프로그램이 명시 적으로 요청했기 때문에 (이 경우 malloc을 사용하여) 런타임에 프로그램에서 사용 가능한 메모리 영역을 나타냅니다.
당신이 끔찍한 코드를 가지고 놀면, 명백하게 잘못된 진술이 모두 세그먼테이션 결함 (치명적인 종료 오류)을 초래하지는 않습니다.
예제 코드에서 이러한 오류를 명시 적으로 만들었지 만 메모리 관리 환경에서 동일한 종류의 오류가 매우 쉽게 발생합니다. 예를 들어 일부 코드가 변수 (또는 다른 기호)의 참조 횟수를 올바른 방식으로 유지하지 않으면 너무 일찍 사용 가능하면 이미 사용 가능한 메모리에서 다른 코드 조각을 읽을 수 있습니다. 주소를 잘못 저장하면 다른 코드가 유효하지 않은 메모리에 쓸 수 있습니다. 두 번 해제 될 수 있습니다 ...
PHP에서 디버깅 할 수있는 문제는 아니며 내부 개발자의주의가 필요합니다.
행동 과정은 다음과 같아야합니다.
이익이 없을 수도 있습니다 ... 처음에 말했다, 당신은 구성을 엉망으로 증상을 변경하는 방법을 찾을 수 있지만, 이것은 매우 치명적이며 그리워하고 다음 번에는 도움이되지 않습니다 같은 zend_mm_heap corrupted
메시지에는 구성 옵션이 너무 많습니다.
버그를 발견 할 때 버그 보고서를 작성하는 것이 매우 중요합니다. 버그를 공격 할 다음 사람이 그럴 것이라고 가정 할 수는 없습니다. 그렇지 않을 경우 실제 해결 방법은 신비하지 않습니다. 올바른 사람들은 문제를 알고 있습니다.
USE_ZEND_ALLOC=0
환경에서 설정 하면 Zend의 자체 메모리 관리자가 비활성화됩니다. Zend의 메모리 관리자는 각 요청에 자체 힙이 있고 요청이 끝날 때 모든 메모리가 해제되도록하며 PHP에 적합한 크기의 메모리 할당에 최적화되어 있습니다.
이를 비활성화하면 이러한 최적화가 비활성화되고, 더 중요한 것은 Zend MM에 의존하여 요청이 끝날 때 메모리를 비우기 위해 많은 확장 코드가 있기 때문에 메모리 누수가 발생할 가능성이 있다는 것입니다 (tut, tut).
증상 을 숨길 수도 있지만 Zend의 힙과 정확히 같은 방식으로 시스템 힙이 손상 될 수 있습니다.
더 관대하거나 덜 관대 해 보일 수 있지만 문제의 근본 원인을 고칠 수는 없습니다 .
이를 비활성화하는 기능은 내부 개발자의 이익을위한 것입니다. Zend MM이 비활성화 된 상태에서 PHP를 배포 해서는 안됩니다 .
PHP 5.5에서 이와 동일한 오류가 발생하여 출력 버퍼링을 늘리는 것이 도움이되지 않았습니다. 나는 APC를 실행하지 않았으므로 문제가되지 않았습니다. 나는 마침내 그것을 opcache 추적했다 . 나는 단순히 cli에서 그것을 비활성화해야했다. 이에 대한 특정 설정이 있습니다.
opcache.enable_cli=0
zend_mm_heap로 전환하면 손상된 오류가 사라졌습니다.
Linux 상자에있는 경우 명령 행에서 시도하십시오.
export USE_ZEND_ALLOC=0
/etc/apache2/envvars
ppas (apt)에서 아파치와 PHP가 모두 설치된 우분투 서버 에서이 줄을 실행하는 경우이 줄을 추가하십시오 . ondrej의 저장소에서 PHP 7.0-RC4를 설치하면이 오류가 발생하기 시작했습니다.
set USE_ZEND_ALLOC=0
unset()
s를 확인하십시오 . 당신이하지 않는 확인 unset()
받는 참조 $this
소멸자에서 (또는 등가물)하고 unset()
좀 연구를 발견 한 같은 객체에 대한 참조 카운트가 0으로 드롭하지 않는 원인 소멸자에들의 일반적으로 힙의 원인을 것을 부패.
있다 zend_mm_heap 손상에 대한 PHP의 버그 리포트 오류가. [2011-08-31 07:49 UTC] f dot ardelian at gmail dot com
그것을 재현하는 방법에 대한 예 는 주석 을 참조하십시오 .
다른 모든 "솔루션"(변경 php.ini
, 더 적은 모듈로 소스에서 PHP 컴파일 등)이 문제를 숨기고 있다고 생각합니다 .
버그 추적기에 따라을 설정하십시오 opcache.fast_shutdown=0
. 빠른 종료는 Zend 메모리 관리자를 사용하여 엉망을 정리합니다.
나는 여기에 하나의 대답이 있다고 생각하지 않으므로 내 경험을 추가 할 것입니다. 임의의 httpd segfault와 함께 동일한 오류가 발생했습니다. 이것은 cPanel 서버였습니다. 문제의 증상은 아파치가 무작위로 연결을 재설정한다는 것입니다 (크롬에서 수신 된 데이터가 없거나 파이어 폭스에서 연결이 재설정되었습니다). 이것들은 무작위로 보였습니다-대부분의 경우 효과가 있었지만 때로는 그렇지 않았습니다.
장면에 도착했을 때 버퍼링이 꺼졌습니다. 출력 버퍼링에 암시 된이 스레드를 읽음으로써 나는 어떤 일이 일어날 지 알기 위해 켰다 (= 4096). 이 시점에서 그들은 모두 오류를 보이기 시작했습니다. 오류가 이제 반복 가능하다는 것이 좋았습니다.
확장 프로그램을 사용하지 않고 시작했습니다. 그중에서도 eaccellerator, pdo, ioncube loader 및 의심스러운 것으로 보였지만 아무런 도움이되지 않았습니다.
마침내 잘못된 PHP 확장명을 "homeloader.so"로 찾았는데 cPanel-easy-installer 모듈의 일종 인 것 같습니다. 제거 후 다른 문제가 발생하지 않았습니다.
참고로, 이는 일반적인 오류 메시지로 표시되므로 마일리지는 다음과 같은 모든 답변에 따라 달라질 수 있습니다.
위의 모든 것을 실패하면 다음과 같은 시도를 할 수도 있습니다.
행운을 빕니다.
나는이 문제로 일주일 동안 씨름했다. 이것은 나를 위해 일했다.
에서하는 것은 php.ini
이러한 변경 작업을
report_memleaks = Off
report_zend_debug = 0
내 설정은
Linux ubuntu 2.6.32-30-generic-pae #59-Ubuntu SMP
with PHP Version 5.3.2-1ubuntu4.7
이 작동하지 않았다.
그래서 벤치 마크 스크립트를 사용해 보았고 스크립트가 끊어진 곳에서 녹음을 시도했습니다. 오류 직전에 php 객체가 인스턴스화되었으며 객체가 수행 해야하는 작업을 완료하는 데 3 초 이상 걸렸지 만 이전 루프에서는 최대 0.4 초가 걸렸습니다. 나는이 테스트를 몇 번, 그리고 매번 동일하게 실행했다. 매번 새로운 객체를 만드는 대신 (여기에는 긴 루프가 있음) 객체를 재사용해야한다고 생각했습니다. 지금까지 스크립트를 12 번 이상 테스트했으며 메모리 오류가 사라졌습니다!
PHP 용 Mongo 2.2 드라이버를 사용 하여이 오류가 발생했습니다.
$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField', 'yetAnotherField'));
^^ 작동하지 않습니다
$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField'));
$collection->ensureIndex(array('yetAnotherField'));
^^ 작동합니다! (?!)
foreach(selectCollection()->find()) { $arr = .. }
PHP 5.3에서 많은 검색을 한 후에 이것은 나를 위해 일한 솔루션입니다.
나는 한 PHP를 가비지 컬렉션 비활성화 추가하여이 페이지를 :
<? gc_disable(); ?>
문제가있는 페이지 끝까지 모든 오류가 사라졌습니다.
소스 .
특성을 사용 중이고 특성이 클래스 이후에로드되는 경우 (즉, 자동로드의 경우) 특성을 미리로드해야합니다.
https://bugs.php.net/bug.php?id=62339
참고 :이 버그는 매우 무작위입니다. 자연 때문입니다.
나에게 문제는 pdo_mysql을 사용하고있었습니다. 쿼리에서 1960 개의 결과가 반환되었습니다. 1900 레코드를 반환하려고 시도했지만 작동합니다. 따라서 문제는 pdo_mysql이며 너무 큰 배열입니다. 원래 mysql 확장명으로 쿼리를 다시 작성하고 작동했습니다.
$link = mysql_connect('localhost', 'user', 'xxxx') or die(mysql_error());
mysql_select_db("db", $link);
Apache는 이전 오류를보고하지 않았습니다.
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)
나를 위해 PHP가 memcached에 세션 정보를 저장하도록 구성 되었기 때문에 memcached 데몬이 충돌했습니다. 100 % CPU를 먹었고 이상하게 행동했습니다. memcached 재시작 후 문제가 사라졌습니다.
일부 도움이 될 수있는 몇 가지 팁
페도라 20, PHP 5.5.18
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;
}
}
var_dummp ()를 사용하면 실제로 오류가 아니며 디버깅을 위해 배치되었으며 프로덕션 코드에서 제거됩니다. 그러나 zend_mm_heap이 발생한 실제 장소는 두 번째입니다.
나는 여기에 같은 상황에 있었고, 위의 아무것도 도움이되지 않았고, 더 심각하게 확인하면서 내 문제를 발견했다. 그리고 "return $ this-> redirect ($ url)"을 만들지 않았습니다.
우물을 재발 명하려고했지만 이것이 문제였습니다.
나는 이것이 누군가를 돕기를 바랍니다!
USE_ZEND_ALLOC=0
오류 로그에 stacktrace를 가져 왔고 버그/usr/sbin/httpd: corrupted double-linked list
를 발견했다opcache.fast_shutdown=1
.