2010-03-25 25 views
15

Có một destructor được gọi nếu ứng dụng bị treo? Nếu đó là một ngoại lệ không được giải quyết, tôi đoán là vậy, nhưng còn những lỗi nghiêm trọng hơn, hoặc một cái gì đó giống như một người dùng giết chết quá trình đăng ký?Destructor - nó có được gọi là nếu ứng dụng bị treo

Và thêm vài câu hỏi có khả năng câm:

  • gì xảy ra với tất cả các đối tượng trong một ứng dụng khi thoát khỏi ứng dụng và tất cả finalizers đã được thực hiện - làm các đối tượng được thu gom rác thải hoặc là họ bằng cách nào đó tất cả " unloaded "với quá trình hoặc appdomain?
  • là bộ phận thu gom rác của mỗi ứng dụng (chạy trong cùng một quy trình) hoặc nó có độc lập không?
+1

Loại sự cố nào? Ngoại lệ không phải là lỗi, nhưng có thể khôi phục được lỗi. – Dykam

Trả lời

21

Tôi khuyến khích bạn tự mình thử điều này. Ví dụ:

using System; 

class Program { 
    static void Main(string[] args) { 
    var t = new Test(); 
    throw new Exception("kaboom"); 
    } 
} 
class Test { 
    ~Test() { Console.WriteLine("finalizer called"); } 
} 

Chạy lệnh này tại dấu nhắc lệnh để bạn có thể nhìn thấy hơi thở cuối cùng. Đầu tiên với tuyên bố ném nhận xét ra.

Giống như bất kỳ ngoại lệ chưa được xử lý nào trong Windows, bộ lọc ngoại lệ mặc định mà Windows cung cấp gọi hộp thoại Báo cáo lỗi Windows, được hiển thị bởi WerFault.exe. Nếu bạn nhấp vào "Đóng chương trình", WerFault sẽ sử dụng TerminateProcess() để giết chương trình. Đó là một kết thúc nhanh chóng, không có cơ hội để chạy thread finalizer, như sẽ xảy ra khi một chương trình thoát bình thường.

Windows sau đó sẽ xử lý việc dọn sạch mảnh đạn. Nó sẽ tự động đóng bất kỳ hệ điều hành nào mà chương trình của bạn xử lý có thể đã mở nhưng không có cơ hội đóng trong trình hoàn thiện. Các tập tin là vấn đề phức tạp hơn ở đây, các bộ đệm của chúng không bị xóa và bạn sẽ dễ dàng kết thúc với một tệp được ghi một phần trên đĩa.

+1

+1. Thx, rất nhiều thông tin. Tôi chắc chắn sẽ cung cấp cho điều này và một vài ý tưởng khác một cố gắng để xem những gì đang xảy ra. – anakic

4

Tôi thậm chí không biết C#, nhưng dựa trên kinh nghiệm của tôi với các ngôn ngữ lập trình khác tôi đoán: Nếu ứng dụng gặp sự cố, điều đó có nghĩa là có sự cố nghiêm trọng với nó. Xử lý bộ nhớ không chính xác vv Thật kỳ lạ đối với bất kỳ ngôn ngữ lập trình nào để cố gắng thực hiện các trình phá hủy/deallocators/finalizers/... trong trường hợp này. Mọi thứ có thể sẽ sai nhiều hơn;)

Cập nhật: (quên trả lời các câu hỏi khác của bạn) một lần nữa, chứ không phải C# - cụ thể, nhưng thường không đảm bảo rằng trình phá hủy/deallocators/finalizers/... thực sự được gọi. Lý do cho điều này là khi một quá trình thoát khỏi nó là dễ dàng hơn và hiệu quả hơn để chỉ đơn giản là "zap" khối bộ nhớ được sử dụng cho quá trình hơn để chạy destructors của nó vv để làm sạch bộ nhớ.

Tôi không chắc chắn cách trả lời câu hỏi cuối cùng của bạn mà không đi vào quá nhiều chi tiết kỹ thuật. Có một số cách mà các nhà sưu tập rác có thể được thiết kế và chạy, dễ nhất là thu gom rác dừng quá trình hiện tại và tiếp tục khi nó được thực hiện, mặc dù cũng có thể (nhưng khó khăn hơn) để thu gom rác chạy đồng thời với các quy trình có bộ nhớ mà họ đang thu thập.

Bạn có thể muốn đọc lên lý thuyết thu thập rác để hiểu rõ hơn về tất cả điều này. Thực sự có toàn bộ trang web về chủ đề này: www.memorymanagement.org.

+0

Thx, câu trả lời hay.Nhưng có một điều dường như không đúng - bạn nói rằng ngay cả khi ứng dụng thoát bình thường, một số destructors vẫn có thể không được gọi ... Có vẻ như không đúng với tôi, vì không có cách nào cho người thu gom rác hoặc bất cứ ai khác (nhưng chính các đối tượng) để biết loại tài nguyên gốc nào mà các đối tượng được quản lý của ứng dụng có thể đã sử dụng, vì vậy nó không thể xử lý được. Dù sao tôi cũng sẽ thử, khi các quý tộc sugested, và đăng kết quả khi tôi có một ít thời gian ... – anakic

+0

Tôi không thể nói cho C#, nhưng Objective-C cung cấp một ví dụ thú vị ở đây. Bạn nên so sánh tài liệu cho 'dealloc' (đó là destructor khi GC bị tắt) và 'finalize' (khi GC được bật). Đối với 'dealloc', các tài liệu nói rất rõ ràng rằng không có đảm bảo rằng nó sẽ được gọi và bạn không nên dựa vào nó để ví dụ đóng một tập tin. Để 'hoàn thành', các tài liệu mờ hơn, có vẻ như gợi ý bạn có thể dựa vào 'hoàn thành' làm 'bản sao lưu' để đảm bảo tệp bị đóng vv, nhưng tôi không thể tìm thấy câu nào rõ ràng là 'hoàn thành' là đảm bảo được gọi. – Rinzwind

+0

Đây là liên kết đến tài liệu cho 'dealloc' và 'finalize' trong Objective-C. BTW: Trong khi chỉ cần thử một thử nghiệm để xem liệu chúng có được gọi trong C# hay không, bạn cũng nên xem tài liệu. Nếu thử nghiệm của bạn cho thấy rằng nó được gọi, nhưng các tài liệu không nói có một * bảo đảm * thì điều này có thể được thay đổi trong các phiên bản tương lai hoặc trên các nền tảng khác, vì vậy bạn nên không dựa vào nó. Tài liệu Obj-C. link: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/dealloc – Rinzwind

3

Nếu giết một ứng dụng, ứng dụng sẽ gần như 100% mất quyền kiểm soát ngay lập tức và không có cơ hội để nó gọi hàm hủy.

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