2011-01-28 71 views
8

Tôi có chức năng đệ quy trong một BaseClass dựa trên chức năng protected virtual cho điều kiện trả lại của nó.Ngăn chặn StackOverFlow trong các hàm đệ quy

Có thể để lớp con ghi đè hàm này không chính xác và dẫn đến ngoại lệ StackOverFlow. Điều tồi tệ nhất là có một số cuộc gọi mạng chậm và ngoại lệ sẽ không xảy ra sớm (nhiều tài nguyên lãng phí trong một thời gian dài).

Tôi đang tìm phương pháp kiểm tra StackOverFlow ở giai đoạn đầu theo cách nào đó trong lớp cơ sở (có thể sử dụng Reflection và mức đệ quy hiện tại).

Bất kỳ ý tưởng nào?

+0

^bỏ phiếu cho chủ đề về stackoverflow. – Robino

Trả lời

8

Bạn có thể vượt qua một số nguyên đơn giản 'sâu' đến chức năng đệ quy và tăng nó với mỗi cuộc gọi tiếp theo. Nếu nó lớn hơn độ sâu tối đa cho phép, hãy ném ngoại lệ ngay sau đó thay vì đợi cho đến khi quá muộn và xảy ra trường hợp ngoại lệ StackOverflow đáng sợ.

Cơ chế an toàn như vậy (bộ đếm gia tăng, kiểm tra nó không quá lớn) cũng có thể hữu ích trong các vòng while trong đó một lỗi nhỏ có thể gây ra một vòng lặp vô hạn tiêu thụ một lượng lớn CPU.

Trong các hệ thống lớn với nhiều người dùng (ví dụ: các trang web) đôi khi tốt nhất là thực hiện các biện pháp phòng ngừa như vậy với đệ quy và vòng lặp vì hậu quả có thể vượt xa một trang web hoặc một người dùng của hệ thống. Nó không phải là mã đẹp và những người theo chủ nghĩa thuần túy sẽ không nghi ngờ gì về nó, nhưng nó hiệu quả, phòng thủ và nó thực dụng.

+3

Không có cách nào, Ian Mercer đăng bài ở đây? – Pierreten

+0

'bool RecursiveConditionMethod (ref int depthLevel) {depthLevel ++; // if (depthLevel> MAX_DEPTH_LEVEL) ngắt vòng lặp' là OK? – Xaqron

+3

@Xaqron, tôi sẽ không sử dụng ref int như thế. Tôi sẽ chỉ chuyển độ sâu + 1 khi phương thức tự gọi và kiểm tra độ sâu đầu tiên bên trong phương thức. Trong một tìm kiếm cây ví dụ bạn có thể không muốn giới hạn tổng số nút truy cập nhưng bạn có thể muốn đảm bảo rằng nó không bị kẹt trong một số vòng lặp vì cây wasn là một cây thích hợp. –

1

Giải quyết sự cố thay vì tạo giải pháp thay thế. Tạo một hàm riêng tư đệ quy gọi hàm ảo được bảo vệ.

+0

Không đời nào. Điều kiện trả về không được tiết lộ cho lớp cơ sở cho đến thời gian chạy và điều này được cung cấp bởi lớp con thông qua việc ghi đè phương thức đó. – Xaqron

+0

? Tại sao lớp cơ sở của bạn phải phụ thuộc vào một lớp con được ghi đè thực hiện? – Pierreten

+1

Các lớp con là các trình cắm thêm chia sẻ rất nhiều công việc thông qua lớp cơ sở. Nếu một đứa trẻ cần phải đi sâu vào nó, nó được cho phép nhưng mã chính nó là bên trong lớp cơ sở và được chia sẻ giữa các trẻ em. – Xaqron

0

Mặc dù bạn có thể đọc chồng cuộc gọi và phân tích nó, tôi sẽ không làm điều đó.

  1. Nó sẽ làm chậm thực hiện
  2. Nó không phải là lớp cơ sở của bạn trách nhiệm
  3. Document lớp cơ sở của bạn hành vi

Một thay thế có thể là để làm phân tích cuộc gọi stack trong chế độ DEBUG chỉ có. Đây là một đoạn mã nhỏ để xem cách để có được ngăn xếp cuộc gọi.

using System.Diagnostics; 

[STAThread] 
public static void Main() 
{ 
    StackTrace stackTrace = new StackTrace();   // get call stack 
    StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) 

    // write call stack method names 
    foreach (StackFrame stackFrame in stackFrames) 
    { 
    Console.WriteLine(stackFrame.GetMethod().Name); // write method name 
    } 
} 

From this site

Các vấn đề liên quan