Giải pháp cho lỗi Fatal: Mức độ lồng tối đa của hàm '100' đạt được, hủy bỏ! trong PHP


137

Tôi đã tạo một hàm tìm tất cả các URL trong tệp html và lặp lại quy trình tương tự cho mỗi nội dung html được liên kết với các URL được phát hiện. Các chức năng là đệ quy và có thể tiếp tục vô tận. Tuy nhiên, tôi đã đặt giới hạn cho đệ quy bằng cách đặt biến toàn cục khiến đệ quy dừng sau 100 lần truy cập.

Tuy nhiên, php trả về lỗi này:

Lỗi nghiêm trọng: Đạt đến mức lồng tối đa của hàm '100', hủy bỏ! trong D: \ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php trên dòng 1355

LỖI

Tôi tìm thấy một giải pháp ở đây: Tăng giới hạn gọi hàm lồng nhưng điều này không hoạt động trong trường hợp của tôi.

Tôi đang trích dẫn một trong những câu trả lời từ liên kết được đề cập ở trên. Hãy xem xét nó.

"Bạn đã cài đặt Zend, IonCube hoặc xDebug chưa? Nếu vậy, đó có lẽ là nơi bạn đang gặp phải lỗi này.

Tôi đã gặp phải điều này một vài năm trước và cuối cùng Zend đặt giới hạn đó ở đó, không phải PHP. Tất nhiên loại bỏ nó sẽ cho phép bạn vượt qua 100 lần lặp, nhưng cuối cùng bạn sẽ đạt đến giới hạn bộ nhớ. "

Có cách nào để tăng mức lồng nhau tối đa trong PHP không


2
Ngoài ra: PHP không có giới hạn đối với các lệnh gọi hàm lồng nhau, nó phải là một phần mở rộng mà bạn đang sử dụng gây ra điều này.
Abel

@ Tin tôi chắc chắn rằng mã của tôi không có lỗi. Có một biến tĩnh làm tăng giá trị của nó lên một trên mỗi cuộc gọi đệ quy. Nếu biến đó nhỏ hơn 100, các cuộc gọi đệ quy sẽ tiếp tục cho đến khi biến đạt 100. Tôi muốn nói rằng biến đạt 100 thực sự là trường hợp cơ sở. Trong khi lỗi phát sinh trước 100 lần thu hồi. Và như bạn đã đề cập rằng một số phần mở rộng mà tôi đang gây ra điều này, tôi muốn đề cập rằng tôi đang sử dụng các hàm từ Simple_html_dom.php. Nếu bạn có bất kỳ ý tưởng nào về Simple_html_dom.php, vui lòng giúp tôi về vấn đề này. Vui lòng tham khảo câu hỏi cập nhật.
Rafay

7
Đó là một lỗi của xdebug. Từ ảnh chụp màn hình, có thể thấy bạn sử dụng xdebug. Bạn có thể tắt cài đặt ở đây: xdebug.max_nesting_level hoặc cho biết mức độ lồng nhau lớn như thế nào.
hakre

3
nếu sử dụng WAMP, lưu ý rằng việc tắt xdebug trong php.ini KHÔNG phải lúc nào cũng hoạt động; áp dụng tương tự cho việc mở rộng mức độ cho phép làm tổ; một lỗi đoán GIẢI PHÁP: truy cập php.ini và nhận xét php_xdebug - ???. Dll
Jeffz

Câu trả lời:


145

Tăng giá trị của xdebug.max_nesting_levelbạnphp.ini


6
@AL Bạn chỉnh sửa tệp php.ini của mình và bạn thêm hoặc chỉnh sửa dòng xdebug.max_nesting_level trong phần XDebug.
Tối đa

3
Tuy nhiên, nếu đây là môi trường sản xuất, hãy xem câu trả lời được chấp nhận, đó là vô hiệu hóa xdebug trong môi trường đó.
zbest

3
Điều này giải quyết các triệu chứng (trong một thời gian), nhưng không phải là vấn đề.
Sebastian Mach

1
Giải pháp này hiệu quả với tôi khi tôi đang sử dụng UFront cho Haxe trên MAMP.
tri kỷ

4
không giới hạn:xdebug.max_nesting_level = -1
Nabi KAZ

55

Một giải pháp đơn giản đã giải quyết vấn đề của tôi. Tôi chỉ nhận xét dòng này:

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

trong php.initập tin của tôi Phần mở rộng này đã giới hạn ngăn xếp để 100tôi vô hiệu hóa nó. Hàm đệ quy hiện đang hoạt động như dự đoán.


4
Vì vậy, cuối cùng nó cũng là phần mở rộng XDebug ... Điều tốt để biết. Trong hai ngày, bạn có thể chấp nhận câu trả lời của riêng mình dưới dạng câu trả lời được chấp nhận, nếu bạn muốn (và xem qua các câu hỏi trước đó của bạn, hầu hết đều bỏ lỡ câu trả lời được chấp nhận).
Abel

61
Đối phó với sự đệ quy quá mức chắc chắn tốt hơn là tắt chế độ giám sát.
petesiss

7
Đó là một cách tiếp cận nặng tay. Các câu trả lời ở trên có đề cập đến biến để điều chỉnh độ sâu ngăn xếp tối đa là cách tiếp cận tốt hơn.
aredridel

7
Bạn sẽ không kích hoạt xdebug trong môi trường sản xuất.
HarryFink

2
tào lao Tôi không thể ngừng cười trước giải pháp đã chọn. Vì vậy, PC của tôi sẽ không ngừng gây ồn, vì vậy tôi đã tìm ra giải pháp. Tắt nó đi. :)
Kevin Remisoski

44

Thay vì thực hiện các cuộc gọi hàm đệ quy, hãy làm việc với một mô hình hàng đợi để làm phẳng cấu trúc.

$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;
}

Có nhiều cách khác nhau để xử lý nó. Bạn có thể theo dõi thêm thông tin nếu bạn cần một số thông tin chi tiết về nguồn gốc hoặc đường dẫn đi qua. Ngoài ra còn có các hàng đợi phân tán có thể hoạt động theo một mô hình tương tự.


5
Với SPL, bạn không cần phải phát minh lại hàng đợi: php.net/manual/en/ class.splqueue.php
Francesco

1
SPL Queue có thể cung cấp tốc độ nhanh hơn một chút, nhưng tôi thích bám vào mảng cho hầu hết các tác vụ đơn giản. đẩy / pop / shift / unshift đều được cung cấp.
Louis-Philippe Huberdeau

1
Đây là câu trả lời chính xác. Tránh thay đổi các giá trị mặc định. Cố gắng tối ưu hóa mã của bạn.
Atique

41

Một giải pháp khác là thêm xdebug.max_nesting_level = 200vào php.ini của bạn


8
cũng có thể làm điều đó bằng php, ví dụ như trong tệp cấu hình của dự án của bạn. ini_set('xdebug.max_nesting_level', 200);
Svassr

@htxryan Tôi không phải là chuyên gia nhưng do ngăn xếp cuộc gọi của bạn quá "sâu" (quá nhiều chức năng gọi các chức năng khác). Kịch bản điển hình trong đó điều này xảy ra là với một hàm đệ quy. Cài đặt rất có thể ở đó để tránh đệ quy "ngoài tầm kiểm soát" do lỗi trong mã.
Bryan

@svassr bạn có thể muốn xem xét thêm mẹo đó như một câu trả lời riêng hoặc thêm vào một câu hỏi hiện có, nó rất hữu ích với tôi nhưng gần như bỏ lỡ nó trong các bình luận
Bryan

@Bryan chỉ cần thêm một câu trả lời
svassr

23

Thay vì vô hiệu hóa xdebug, bạn có thể đặt giới hạn cao hơn như

xdebug.max_nesting_level = 500


@SebastianMach: và, thật đáng kinh ngạc, nhiều năm sau, cũng vậy. :) (Giống như bốn lần nữa, hoặc hơn thế. Mọi người không chỉ không đọc bây giờ, họ thậm chí không cuộn nữa.)
Sz.

1
@Sz.: Wow, thật là một vụ nổ từ quá khứ: P Thật đáng kinh ngạc.
Sebastian Mach

18

Cũng có thể sửa lỗi này trực tiếp trong php, ví dụ như trong tệp cấu hình của dự án của bạn.

ini_set('xdebug.max_nesting_level', 200);


1
Cảm ơn, điều này hoạt động tốt vì tôi không phải lo lắng về việc cập nhật php.ini trên tất cả các hộp dev của mình, tôi chỉ cần thêm nó vào tệp bootstrap của ứng dụng.
Bryan

13

Đi vào tệp cấu hình php.ini của bạn và thay đổi dòng sau:

xdebug.max_nesting_level=100

đến một cái gì đó như:

xdebug.max_nesting_level=200

13

trên Ubuntu bằng PHP 5.59:
got to `:

/etc/php5/cli/conf.d

và tìm xdebug.ini của bạn trong thư mục đó, trong trường hợp của tôi là 20-xdebug.ini

và thêm dòng này `

xdebug.max_nesting_level = 200


hoặc cái này

xdebug.max_nesting_level = -1

đặt nó thành -1 và bạn không phải lo lắng thay đổi giá trị của mức lồng nhau.

`


12

có lẽ đã xảy ra vì xdebug.

Hãy thử nhận xét dòng sau trong "php.ini" của bạn và khởi động lại máy chủ của bạn để tải lại PHP.

  ";xdebug.max_nesting_level"


2
hoặc vô hiệu hóa tất cả
xdebug

2
Làm thế nào điều này sẽ làm việc? Nếu bạn không xác định giới hạn theo cách thủ công, nó sẽ chỉ trở về mặc định là 100 ( xdebug.org/docs/basic ). Bằng cách nhận xét dòng này, tất cả những gì bạn làm nó buộc cài đặt trở lại mặc định.
justanotherprogrammer 10/12/13

Vô hiệu hóa tất cả xdebug không được khuyến nghị nếu bạn phụ thuộc vào việc sử dụng công cụ của anh ấy; Thông thường, cấu hình "xdebug.max_nesting_level" được sử dụng mà không biết công dụng thực sự của anh ấy, vì vậy nói chung chỉ nhận xét là đủ và hợp lệ.
vandersondf

12

Hãy thử tìm trong /etc/php5/conf.d/ để xem có tệp nào có tên xdebug.ini không

max_nesting_level là 100 theo mặc định

Nếu nó không được đặt trong tập tin đó, hãy thêm:

xdebug.max_nesting_level=300

đến cuối danh sách để nó trông như thế này

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

sau đó bạn có thể sử dụng @ Andrey của bài kiểm tra trước và sau khi thực hiện thay đổi này để xem nếu làm việc.

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

Tuyệt vời, câu trả lời đầu tiên đề cập rằng xdebug có một .initệp riêng . Nhân tiện, khi bạn chạy php5-fpm, tập tin này có thể ở đâu đó tại đây:/etc/php5/fpm/conf.d/20-xdebug.ini
Daan

7

php.ini:

xdebug.max_nesting_level = -1

Tôi không hoàn toàn chắc chắn liệu giá trị có bao giờ tràn và đạt -1 hay không, nhưng nó sẽ không bao giờ đạt tới -1, hoặc nó sẽ đặt max_nesting_level khá cao.


Nó hoạt động! Bất kể bạn có sử dụng XDebug hay không, nếu bạn bình luận dòng trong php.ini. Tôi đã sử dụng rõ ràng: ini_set ('xdebug.max_nesting_level', -1);
dùng2928048

6

Bạn có thể chuyển đổi mã đệ quy thành mã lặp, mô phỏng đệ quy. Điều này có nghĩa là bạn phải đẩy trạng thái hiện tại (url, tài liệu, vị trí trong tài liệu, v.v.) vào một mảng, khi bạn đạt đến một liên kết và bật nó ra khỏi mảng, khi liên kết này kết thúc.


5

Bạn có thể thử vẫy xuống lồng nhau bằng cách thực hiện các công nhân song song (như trong điện toán cụm) thay vì tăng số lượng các lệnh gọi hàm lồng nhau.

Ví dụ: bạn xác định số lượng vị trí giới hạn (ví dụ: 100) và theo dõi số lượng "công nhân" được chỉ định cho mỗi / một số trong số chúng. Nếu bất kỳ vị trí nào trở nên miễn phí, bạn đặt nhân viên chờ "trong đó".


1
Đó không thực sự là một cách tiếp cận thường áp dụng. Điều đó hợp lý hơn để song song, không tránh độ sâu ngăn xếp.
aredridel

5

Kiểm tra đệ quy từ dòng lệnh:

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

nếu kết quả> 100 THEN kiểm tra giới hạn bộ nhớ;


3

Nếu bạn đang sử dụng Laravel, hãy làm

composer update

Đây nên là công việc.


Bạn nên thêm thông tin cơ bản về điều này. Điều này có thể hữu ích mặc dù laracasts.com/forum/ từ
ggderas

1
điều này không ảnh hưởng đến cài đặt xdebug / php.ini có thể là nguyên nhân gây ra lỗi. Cũng có thể ứng dụng của bạn đang ở trong một vòng lặp dos và liên tục lặp xung quanh một chức năng, không biết OP đã sử dụng laravel ở đâu và nhìn vào mã của anh ta có khả năng là codeigniter
James Kirkby

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

PS Thay đổi 9999 thành bất kỳ số nào bạn muốn.


1

Tôi đã gặp lỗi khi cài đặt nhiều plugin Vì vậy, lỗi 100 hiển thị bao gồm cả vị trí của plugin cuối cùng mà tôi đã cài đặt C: \ wamp \ www \ mysite \ wp-content \ plugins \ "..." vì vậy tôi đã xóa plugin này thư mục trên ổ C: sau đó mọi thứ đã trở lại bình thường. Tôi nghĩ rằng tôi phải giới hạn số lượng trình cắm tôi đã cài đặt hoặc đã kích hoạt. thật may mắn tôi hy vọng nó sẽ giúp


1

Trong trường hợp của bạn, chắc chắn phiên bản trình thu thập thông tin có giới hạn Xdebug nhiều hơn để theo dõi lỗi và thông tin gỡ lỗi.

Tuy nhiên, trong các trường hợp khác, các lỗi như trên PHP hoặc các tệp lõi như thư viện CodeIgniter sẽ tạo ra trường hợp như vậy và nếu bạn thậm chí tăng cài đặt mức gỡ lỗi x thì nó sẽ không biến mất.

Vì vậy, hãy nhìn vào mã của bạn một cách cẩn thận :).

Đây là vấn đề trong trường hợp của tôi.

Tôi đã có một lớp dịch vụ là thư viện trong CodeIgniter. Có một chức năng bên trong như thế này.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

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

Bộ điều khiển của tôi như sau:

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

Chức năng gọi trên dòng cuối cùng đã sai vì lỗi đánh máy, thay vào đó nó phải giống như dưới đây:

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

Sau đó, tôi đã tiếp tục nhận được thông báo lỗi vượt quá. Nhưng tôi đã vô hiệu hóa XDebug nhưng không giúp được. Bất kỳ cách nào xin vui lòng kiểm tra tên lớp hoặc mã của bạn để gọi hàm đúng.


Đó là một câu trả lời hay một câu hỏi?
AL

@d kèmad Tôi đã chỉnh sửa câu trả lời của bạn, tôi nghĩ rằng tốt hơn là viết giải pháp bằng văn bản và không chỉ trong các nhận xét được đính kèm theo mã. Và hình thức hiện tại làm tôi nghĩ rằng đó là một câu hỏi mới và không phải là một câu trả lời. Vui lòng quay lại nếu bạn không chấp nhận các thay đổi.
AL

1

Tôi đã có vấn đề này với WordPress trên cloud9. Hóa ra đó là plugin W3 Cache. Tôi đã tắt plugin và nó hoạt động tốt.


1

Một giải pháp khác nếu bạn đang chạy tập lệnh php trong CLI (cmd)

Tệp php.ini cần chỉnh sửa là khác nhau trong trường hợp này. Trong cài đặt WAMP của tôi, tệp php.ini được tải trong dòng lệnh là:

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

thay vì \ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini sẽ tải khi php chạy từ trình duyệt


0

Bạn cũng có thể sửa đổi hàm {debug} trong modifier.debug_print_var.php, để hạn chế đệ quy của nó vào các đối tượng.

Khoảng dòng 45, trước:

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

Sau :

$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));

Bằng cách này, Xdebug vẫn sẽ hoạt động bình thường: giới hạn độ sâu đệ quy trong var_dump, v.v. Vì đây là một vấn đề thông minh, không phải là một Xdebug!


0

Tôi đã có cùng một vấn đề và tôi reslove như thế này:

Mở tệp tin my.ini của MySQL

Trong phần [mysqld], thêm dòng sau: innodb_force_recovery = 1

Lưu tệp và thử bắt đầu MySQL

Xóa dòng mà bạn vừa thêm và Lưu

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.