"치명적 오류 : 최대 기능 중첩 수준 '100'에 도달했습니다. 중단되었습니다!" PHP에서


137

html 파일 내에서 모든 URL을 찾고 검색 된 URL에 연결된 각 html 컨텐츠에 대해 동일한 프로세스를 반복하는 기능을 만들었습니다. 이 함수는 재귀 적이며 끝없이 진행될 수 있습니다. 그러나 100 회 재귀 후 재귀가 중지되도록 전역 변수를 설정하여 재귀를 제한했습니다.

그러나 PHP는 다음 오류를 반환합니다.

치명적인 오류 : 최대 기능 중첩 수준 '100'에 도달하여 중단되었습니다! D : \ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php의 1355 행

오류

여기에서 해결책을 찾았습니다 : 중첩 함수 호출 제한을 늘리지 만 제 경우에는 작동하지 않습니다.

위에서 언급 한 링크에서 답변 중 하나를 인용하고 있습니다. 그것을 고려하십시오.

"Zend, IonCube 또는 xDebug가 설치되어 있습니까? 그렇다면이 오류가 발생했을 수 있습니다.

몇 년 전에이 문제가 발생하여 PHP가 아닌 Zend가 그 한계를 뛰어 넘었습니다. 물론 이것을 제거하면 100 번의 반복을 지나갈 수 있지만 결국 메모리 한계에 도달하게됩니다. "

PHP에서 최대 함수 중첩 수준을 높이는 방법이 있습니까?


2
또한 : PHP는 중첩 함수 호출에 제한이 없으므로 사용하는 확장명이어야합니다.
Abel

@ 아벨 내 코드에 오류가 없다고 확신합니다. 각 재귀 호출마다 값을 하나씩 증가시키는 정적 변수가 있습니다. 해당 변수가 100보다 작은 경우 재귀 호출은 변수가 100에 도달 할 때까지 계속됩니다. 100에 도달하는 변수가 실제로 기본 사례라고합니다. 100 회귀 전에 오류가 발생합니다. 그리고 당신이 내 확장을 유발한다고 언급했듯이, simple_html_dom.php의 함수를 사용하고 있다고 언급하고 싶습니다. simple_html_dom.php에 대한 아이디어가 있으면 이와 관련하여 도와주세요. 업데이트 된 질문을 참조하십시오.
Rafay

7
그것은 xdebug에 의한 오류입니다. 스크린 샷에서 xdebug를 사용하고 있습니다. 여기서 설정을 비활성화 할 수 있습니다 : xdebug.max_nesting_level 또는 중첩 수준의 크기를 알려줍니다.
hakre

3
WAMP를 사용하는 경우 php.ini에서 xdebug를 비활성화해도 항상 작동하지는 않습니다. 허용 된 중첩 수준을 확장 할 때도 마찬가지입니다. 버그 추측; 해결책 : php.ini로 가서 php_xdebug-???. dll을 주석 처리하십시오
Jeffz

답변:


145

의 가치를 높이 xdebug.max_nesting_level십시오php.ini


6
@AL php.ini 파일을 편집하고 XDebug 섹션에서 xdebug.max_nesting_level 행을 추가하거나 편집합니다.
Maxence

3
그러나 이것이 프로덕션 환경 인 경우 해당 환경에서 xdebug를 비활성화하는 허용되는 답변을 참조하십시오.
zkent

3
이렇게하면 증상이 한동안 해결되지만 문제는 해결되지 않습니다.
Sebastian Mach

1
이 솔루션은 MAMP에서 Haxe에 UFront를 사용할 때 효과적이었습니다.
Confidant

4
무제한 :xdebug.max_nesting_level = -1
Nabi KAZ

55

간단한 해결책으로 문제가 해결되었습니다. 방금이 줄을 주석 처리했습니다.

zend_extension = "d:/wamp/bin/php/php5.3.8/zend_ext/php_xdebug-2.1.2-5.3-vc9.dll

php.ini 파일에. 이 확장은 스택을 제한하여 100비활성화했습니다. 재귀 함수는 이제 예상대로 작동합니다.


4
결국 결국 XDebug 확장이었습니다. 원하는 경우 이틀 안에 자신의 답변을 수락 된 답변으로 수락 할 수 있습니다.
Abel

61
과도한 재귀를 처리하는 것은 모니터링을 끄는 것보다 낫습니다.
petesiss

7
이는 엄중 한 접근 방식입니다. 최대 스택 깊이를 조정하는 변수를 언급하는 위의 답변이 더 나은 방법입니다.
aredridel

7
프로덕션 환경에서 xdebug가 활성화되어 있지 않습니다.
HarryFink

2
이런 세상에. 선택한 솔루션을보고 웃을 수 없습니다. 그래서 내 PC는 소음을 멈추지 않을 것이므로 해결책을 찾았습니다. 전원을 끄십시오. :)
Kevin Remisoski 4

44

재귀 함수 호출을 수행하는 대신 큐 모델을 사용하여 구조를 평탄화하십시오.

$queue = array('http://example.com/first/url');
while (count($queue)) {
    $url = array_shift($queue);

    $queue = array_merge($queue, find_urls($url));
}

function find_urls($url)
{
    $urls = array();

    // Some logic filling the variable

    return $urls;
}

그것을 처리하는 다른 방법이 있습니다. 통과 한 원점이나 경로에 대한 통찰력이 필요한 경우 자세한 정보를 추적 할 수 있습니다. 유사한 모델을 해결할 수있는 분산 큐도 있습니다.


5
SPL을 사용하면 대기열을 다시 만들 필요가 없습니다. php.net/manual/en/class.splqueue.php
Francesco

1
SPL Queue는 약간 더 빠른 속도를 제공하지만 가장 간단한 작업을 위해 어레이를 고수하는 것을 좋아합니다. 푸시 / 팝 / 시프트 / 언 시프트가 모두 제공됩니다.
Louis-Philippe Huberdeau

1
이것이 정답입니다. 기본값을 변경하지 마십시오. 코드를 최적화하십시오.
Junaid Atique

41

또 다른 해결책은 xdebug.max_nesting_level = 200php.ini 에 추가 하는 것입니다


8
예를 들어 프로젝트의 구성 파일에서 PHP로 수행 할 수도 있습니다. ini_set('xdebug.max_nesting_level', 200);
svassr

@htxryan 전문가는 아니지만 호출 스택이 너무 "깊어"(다른 함수를 호출하는 함수가 너무 많음) 때문입니다. 이러한 상황이 발생하는 일반적인 시나리오는 재귀 함수입니다. 이 설정은 코드의 버그로 인한 "제어 불능"재귀를 피할 가능성이 높습니다.
Bryan

@svassr 당신은 그 팁을 별도의 답변으로 추가하거나 기존 팁에 추가하는 것을 고려하고 싶을 것입니다. 그것은 도움이되었지만 댓글에서 거의 놓쳤습니다.
Bryan

그냥 대답 추가 @Bryan
svassr

23

xdebug를 비활성화하는 대신 다음과 같이 더 높은 한계를 설정할 수 있습니다

xdebug.max_nesting_level = 500


@SebastianMach : 그리고 놀랍게도 몇 년 후. :) (4 번 정도 더 그렇습니다. 사람들은 지금 읽을뿐만 아니라 더 이상 스크롤하지도 않습니다.)
Sz.

1
@Sz .: 와우, 과거로부터의 폭발 : P 놀랍도록 충격적입니다.
Sebastian Mach

18

예를 들어 프로젝트의 구성 파일과 같이 PHP에서 직접 수정할 수도 있습니다.

ini_set('xdebug.max_nesting_level', 200);


1
고마워, 이것은 모든 dev 상자에서 php.ini 업데이트에 대해 걱정할 필요가 없으므로 잘 작동합니다. 응용 프로그램의 부트 스트랩 파일에 추가하면됩니다.
Bryan

13

php.ini 구성 파일로 이동하여 다음 줄을 변경하십시오.

xdebug.max_nesting_level=100

같은 것 :

xdebug.max_nesting_level=200

13

PHP 5.59를 사용하는 우분투에서
:

/etc/php5/cli/conf.d

그 디렉토리에서 xdebug.ini 를 찾으십시오 . 제 경우에는 20-xdebug.ini입니다.

이 줄을 추가하십시오`

xdebug.max_nesting_level = 200


아니면 이거

xdebug.max_nesting_level = -1

-1로 설정하면 중첩 수준의 값을 변경할 걱정이 없습니다.

`


12

아마도 xdebug 때문에 발생했을 것입니다.

"php.ini" 에 다음 줄을 주석으로 달고 서버를 다시 시작하여 PHP를 다시로드하십시오.

  ";xdebug.max_nesting_level"


2
또는 모든 Xdebug는 비활성화
zloctb

2
이것은 어떻게 작동합니까? 제한을 수동으로 정의하지 않으면 기본값 인 100 ( xdebug.org/docs/basic ) 으로 되돌아갑니다 . 이 줄을 주석 처리하면 설정이 기본값으로 되돌아갑니다.
justanotherprogrammer

도구 사용에 의존하는 경우 모든 xdebug를 사용하지 않는 것이 좋습니다. 일반적으로 "xdebug.max_nesting_level"구성은 실제로 사용하지 않고 사용되므로 일반적으로 주석만으로 충분합니다.
vandersondf

12

/etc/php5/conf.d/에서 xdebug.ini라는 파일이 있는지 확인하십시오.

max_nesting_level은 기본적으로 100입니다

해당 파일에 설정되어 있지 않으면 다음을 추가하십시오.

xdebug.max_nesting_level=300

목록의 끝 부분에

xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/home/drupalpro/websites/logs/profiler
xdebug.max_nesting_level=300

그런 다음 @Andrey의 테스트 를 사용 하여이 변경 전후에 작동하는지 확인할 수 있습니다.

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

xdebug에 별도의 .ini파일 이 있다고 언급 한 첫 번째 대답입니다 . 그런데 php5-fpm을 실행할 때이 파일은 아마도 다음 위치에있을 것입니다 :/etc/php5/fpm/conf.d/20-xdebug.ini
Daan

7

php.ini :

xdebug.max_nesting_level = -1

값이 오버플로되어 -1에 도달하는지 확실하지 않지만 -1에 도달하지 않거나 max_nesting_level을 꽤 높게 설정합니다.


효과가있다! XDebug 사용 여부에 관계없이 php.ini에서 줄을 주석 처리하지 않아도됩니다. 명시 적으로 사용했습니다 : ini_set ( 'xdebug.max_nesting_level', -1);
user2928048

6

재귀 코드를 반복 코드로 변환하여 재귀를 시뮬레이션 할 수 있습니다. 즉, 링크에 도달하면 현재 상태 (URL, 문서, 문서의 위치 등)를 배열로 푸시하고이 링크가 완료되면 배열에서 튀어 나와야합니다.


5

중첩 함수 호출 수를 늘리는 대신 (클러스터 컴퓨팅과 같이) 병렬 작업자를 구현하여 중첩을 축소 할 수 있습니다.

예를 들어, 제한된 수의 슬롯 (예 : 100)을 정의하고 각 슬롯에 할당 된 "작업자"수를 모니터링합니다. 슬롯이 비어 있으면 대기중인 작업자를 "그 안에"넣습니다.


1
그것은 실제로 일반적으로 적용 가능한 접근 방식이 아닙니다. 스택 깊이를 피하지 않고 병렬화하는 것이 더 합리적입니다.
aredridel

5

명령 행에서 재귀를 점검하십시오.

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

결과> 100 THEN이면 메모리 한계를 점검하십시오.


3

라 라벨을 사용한다면

composer update

이것은 작동해야합니다.


이에 대한 배경 정보를 더 추가해야합니다. 이것은 laracasts.com/forum/…
ggderas

1
이것은 xdebug / php.ini 설정과 관련이 없으며 오류의 원인이 될 수 있습니다. 응용 프로그램이 dos 루프에 있고 함수 주위에서 지속적으로 반복 될 가능성도 있습니다. OP 상태에서 laravel을 사용하고 있으며 코드 코드를 살펴보면 코드 점화기가 될 가능성이 없습니다
James Kirkby

3
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

PS 원하는 숫자로 9999를 변경하십시오.


1

많은 플러그인을 설치할 때 오류가 발생했습니다. 따라서 오류 100은 C : \ wamp \ www \ mysite \ wp-content \ plugins \ "..."를 설치 한 마지막 플러그인의 위치를 ​​포함하여 표시했습니다. C의 폴더 : 드라이브 다음 모든 것이 정상으로 돌아 왔습니다. 설치하는 플러그인의 양을 제한해야한다고 생각합니다. 설치하거나 활성화했습니다. 행운이 도움이되기를 바랍니다.


1

귀하의 경우 크롤러 인스턴스에 오류 및 디버그 정보를 추적하기 위해 더 많은 Xdebug 제한이 있습니다.

그러나 다른 경우에는 PHP 또는 CodeIgniter 라이브러리와 같은 핵심 파일과 같은 오류가 발생하며 x-debug 레벨 설정을 높이더라도 사라지지 않습니다.

따라서 코드를 신중하게 살펴보십시오. :).

내 경우에는 문제가있었습니다.

CodeIgniter에 라이브러리 인 서비스 클래스가 있습니다. 이와 같은 기능을 가지고 있습니다.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

  public function process(){
   //lots of Ci referencing here...
   }

내 컨트롤러는 다음과 같습니다.

$this->load->library('PaymentService');
$this->process_(); // see I got this wrong instead  it shoud be like 

오타로 인해 마지막 줄의 함수 호출이 잘못되었습니다. 대신 다음과 같아야합니다.

$this->Payment_service->process(); //the library class name

그런 다음 초과 오류 메시지가 계속 나타납니다. 그러나 XDebug를 비활성화했지만 도움이되지 않았습니다. 어쨌든 클래스 이름이나 코드에서 적절한 함수 호출을 확인하십시오.


답입니까, 질문입니까?
AL

@ daniedad 귀하의 답변을 편집했습니다 . 코드에 첨부 된 주석뿐만 아니라 텍스트로 솔루션 을 작성하는 것이 좋습니다 . 그리고 현재의 형태는 그것이 새로운 질문이 아니라 대답이라고 생각하게 만들었습니다. 변경 사항을 승인하지 않으면 언제든지 롤백하십시오.
AL

1

cloud9에서 WordPress 에이 문제가있었습니다. W3 캐싱 플러그인이었습니다. 플러그인을 비활성화하고 정상적으로 작동했습니다.


1

CLI (cmd)에서 PHP 스크립트를 실행하는 경우 다른 솔루션

이 경우 편집이 필요한 php.ini 파일이 다릅니다. 내 WAMP 설치에서 명령 줄에로드 된 php.ini 파일은 다음과 같습니다.

\wamp\bin\php\php5.5.12\php.ini

브라우저에서 PHP를 실행할 때로 드되는 \ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini 대신


0

객체로의 재귀를 제한하기 위해 modifier.debug_print_var.php에서 {debug} 함수를 수정할 수도 있습니다.

45 행 전 :

$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);

후 :

$max_depth = 10;
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . ($depth > $max_depth ? 'Max recursion depth:'.(++$depth) : smarty_modifier_debug_print_var($curr_val, ++$depth, $length));

이런 식으로 Xdebug는 여전히 정상적으로 동작합니다 : var_dump의 재귀 깊이 제한 등. 이것은 Xdebug가 아닌 현명한 문제입니다!


0

나는 똑같은 문제가 있었고 나는 이렇게 reslove :

MySQL my.ini 파일을 엽니 다

[mysqld] 섹션에서 다음 행을 추가하십시오. innodb_force_recovery = 1

파일을 저장하고 MySQL을 시작하십시오

방금 추가 한 줄을 제거하고 저장하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.