2011-01-19 32 views
20

Kịch bản:Làm thế nào để gỡ lỗi một StackOverflowException trong .NET

Tôi vừa mới được trên một cuộn và thực hiện một loạt các mã, nhưng khi tôi thực hiện nó tôi nhận được ném một StackOverflowException? StackOverflowException không có stacktrace nên tôi bị kẹt. Tôi biết lý do tại sao một tràn ngăn xếp có thể xảy ra, nhưng để sửa chữa nó, tôi cần biết gốc của nó ở đâu.

Tất cả tôi nhận được là: Một ngoại lệ unhandled của loại 'System.StackOverflowException' xảy ra trong thẻ-bạn-it.dll

Options:

  1. Scan qua tất cả các thay đổi và cố gắng chỉ ra vấn đề. (có thể chậm)
  2. Sử dụng trình gỡ lỗi và đi qua cho đến khi bạn tìm thấy sự cố. (có thể tốt hơn 1.)
  3. Sử dụng hồ sơ và tìm các phương pháp được gọi nhiều nhất.
  4. ?

PS:

Đây là một tình huống giả định (mặc dù không phải là quá phổ biến) và do đó không có mã có sẵn.

+0

In ra stacktrace? VS có xu hướng bị nghẹt thở khi đối mặt với một ngoại lệ stackoverflow. – leppie

+0

Mã gây ra điều này được công khai trong liên kết trong câu hỏi http://stackoverflow.com/questions/39004357/how-to-fix-stackoverflowexception-in-net – Andrus

Trả lời

12

Điều này hầu như luôn luôn là do đệ quy. Hoặc là một phương thức tự gọi chính nó, hoặc một phương thức gọi một phương thức gọi nó trở lại và vân vân.

Để tìm nó:

  • CẬP NHẬT: Tôi đã không nhận ra, nhưng dường như bạn không thể nhận stack trace cho một StackOverflowException (Tôi đoán điều gì đó để làm với việc không thể xem một vở kịch , hoặc). Tuy nhiên có nhiều cách để có được một bãi chứa as mentioned here.
  • ReSharper sẽ hiển thị các phương thức tự gọi mình (nó đặt một vòng tròn nhỏ màu xanh ở thanh bên cho các cuộc gọi đệ quy) mặc dù nó sẽ không bắt đệ quy khi có hai hoặc nhiều phương pháp tham gia.
  • Sử dụng công cụ như ANTS Profiler để xem phương pháp nào được gọi nhiều nhất.
  • Hãy theo dõi các sự kiện phát sinh có thể gọi mã có nghĩa là sự kiện tương tự sẽ kích hoạt trở lại, gây ra một vòng lặp.

Đôi khi bạn sẽ nhận được lỗi chính tả như thế này, quá:

private string name; 

public string Name 
{ 
    get { return Name; } // Ooops! This is recursive, all because of a typo... 
} 

Đó là lý do tại sao cá nhân tôi hiện nay thích sử dụng các thuộc tính tự động.

+3

1. Bạn không nhận được một stacktrace với một ngoại lệ SO. 2. đệ quy có lẽ là thủ phạm và resharper có thể giúp đỡ, nhưng sau đó nó không luôn luôn giúp đỡ để tìm vòng tròn do các cấu trúc khác. 3. Một hồ sơ trông giống như một lựa chọn tốt. – Christo

+0

http://stackoverflow.com/questions/39004357/how-to-fix-stackoverflowexception-in-net/ cho thấy rằng điều này không phải do đệ quy. Làm thế nào để gỡ lỗi SOexception trong trường hợp này? Câu trả lời này giả định rằng điều này là do đệ quy. – Andrus

-1

Tìm các phương thức tự gọi (hoặc một phương pháp gọi một phương thức khác và ngược lại) và kiểm tra chúng. Đệ quy thường là nghi phạm chính khi bạn nhận được ngoại lệ SO.

+1

Tôi biết tại sao chúng xảy ra. Sự cố đang theo dõi chúng. Bạn chỉ cần nêu rõ lựa chọn 1. – Christo

1

Tại phương thức là "điểm vào" cho thao tác không thành công, hãy đặt điểm ngắt. Bước qua mã và xem cho các lần xuất hiện của cùng một chuỗi các cuộc gọi phương thức xảy ra lặp đi lặp lại trong một mẫu giống hệt nhau để ngăn xếp cuộc gọi ngày càng sâu hơn.

Ngay khi bạn nhận thấy điều đó, hãy đặt điểm ngắt tại vị trí hiện tại, ở bất kỳ đâu. Tiếp tục thực hiện (F5 trong Visual Studio) - nếu bạn đang đi đúng hướng thì trình gỡ lỗi sẽ dừng lại rất nhanh tại cùng một vị trí và ngăn xếp cuộc gọi sẽ còn sâu hơn nữa.

Bây giờ bạn có khung ngăn xếp "trực tiếp", bạn có thể kiểm tra, để tìm hiểu cách đảm bảo rằng đệ quy này sẽ chấm dứt đúng cách.

+0

Giống như gợi ý của Borja. – Christo

+0

Cách khác xung quanh (sắp xếp câu trả lời bằng 'Cũ nhất') –

+0

;-) Jip, đoán phân loại của tôi là sai. Tôi đã ban đầu bỏ phiếu của bạn lên là tốt, chỉ trong trường hợp tôi đã đặt hàng sai. – Christo

5

Bạn có thể thực thi chương trình trên chế độ gỡ lỗi và tạm dừng nó. Trên callstack hiện tại bạn có thể thấy rằng có một phương pháp hoặc một nhóm phương pháp xuất hiện nhiều lần, đây là những phương pháp có vấn đề. Đặt một điểm break trên phương pháp này và nhìn những gì nó gọi là chính nó tất cả các thời gian.

+0

True, tôi sẽ thêm bước thông qua gỡ lỗi như một tùy chọn khác. – Christo

+0

Cảm ơn!Tôi chỉ thỉnh thoảng gặp lỗi gnarly và vì vậy tôi không có thói quen sử dụng Call Stack. Tôi đã * chắc chắn * rằng tôi không có vấn đề đệ quy nhưng, tất nhiên, tôi đã có một vấn đề đệ quy ở một vị trí bất ngờ và sửa chữa rất dễ dàng một khi tôi dừng lại chỉ cố gắng để intuit những gì đã sai. :-) – clweeks

5

Đi tới Gỡ lỗi, ngoại lệ và chọn hộp kiểm được ném tại 'Ngoại lệ thời gian chạy ngôn ngữ chung'. Bây giờ khi bạn gây ra ngoại lệ stackoverflow, trình gỡ lỗi sẽ dừng (cuối cùng) và hiển thị cho bạn ngăn xếp cuộc gọi.

+2

Bạn có chắc chắn rằng nó hoạt động trên các ngoại lệ tràn ngăn xếp? Họ là một chút đặc biệt trong cách họ được xử lý. –

+1

. Tôi đã làm xong. – Joshua

+2

Có lẽ đáng chú ý bạn cần phải nhìn vào cửa sổ Call Stack của Visual Studio không phải StackTrace của Exception mà sẽ không được thiết lập (có thể bởi vì một khi ngăn xếp đầy, nó không thể làm bất cứ thứ gì cần dùng thêm). – Appetere

0

Nếu bạn có mã và có thể chạy chương trình của bạn từ Visual Studio, nó sẽ bị ngắt trong trình gỡ rối (nếu ngoại lệ đầu tiên được kích hoạt) khi gặp sự cố System.StackOverflowException. Từ đó bạn có thể kiểm tra ngăn xếp cuộc gọi và xem cuộc gọi nào đang thổi ngăn xếp. enter image description here

Tôi đã xác nhận rằng tính năng này hoạt động cho Visual Studio 2010 và Visual C# 2010 Express.

0

Cá nhân, tôi muốn thu hẹp nó càng nhiều càng tốt vào một phần mã nhất định. Ví dụ, tôi chỉ có một. Điều kỳ lạ là nó chỉ xảy ra trên máy tôi không thể gỡ lỗi trực tiếp.

Tôi có hai luồng chạy song song, vì vậy tôi đã ngừng chạy một luồng (hoặc bạn có thể vô hiệu hoá nó).

Sau đó, tôi đã trải qua các chức năng của mình và bổ sung như chức năng in ra, chẳng hạn như: Cũng giống như chức năng bắt đầu:

Console.WriteLine("<Enter method: {0}", DebuggingHelper.GetCurrentMethod()); 

Ngay trước khi trở về chức năng:

Console.WriteLine(">Exit method: {0}", DebuggingHelper.GetCurrentMethod()); 

đâu GetCurrentMethod được định nghĩa là :

[MethodImpl(MethodImplOptions.NoInlining)] 
public static string GetCurrentMethod() 
{ 
    StackTrace st = new StackTrace(); 
    StackFrame sf = st.GetFrame(1); 
    return sf.GetMethod().Name; 
} 

Sau đó, tôi chạy nó, có thể tôi không thêm cho tất cả các chức năng, nhưng đủ để thu hẹp vị trí trong mã đang xảy ra. Sau đó, trong phần đó, thêm nhiều hơn nữa.

Bạn cũng có thể thêm điểm kiểm tra khi nó chạy qua một số phương pháp nhất định.

Sau đó chạy lại, những gì bạn sẽ thấy là ngoại lệ StackOverFlow sẽ xảy ra giữa các câu lệnh đó. Tiếp tục thu hẹp cho đến khi bạn tìm thấy nó.

Khá đơn giản và nhanh chóng để tìm nơi xảy ra theo cách này.

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