2010-08-25 41 views
5

Quy tắc chung, chỉ các đối tượng được phân bổ trong cửa hàng miễn phí mới có thể gây rò rỉ bộ nhớ. Nhưng các đối tượng được tạo trong ngăn xếp thì không.Đây có phải là rò rỉ bộ nhớ không?

Đây là nghi ngờ của tôi,

int main() 
    { 
     myclass x; 

     ... 

     throw; 

     ... 
    } 

Nếu ném không được xử lý, nó gọi, chấm dứt(), mà lần lượt các cuộc gọi hủy bỏ() và bị treo ứng dụng. Tại thời điểm này, các đối tượng trong ngăn xếp không phải là destoryed (The destructor không được gọi).

sự hiểu biết của tôi là "Khi chấm dứt ứng dụng (hoặc bằng cách hủy bỏ hoặc bởi lối bình thường), nó giải phóng tất cả các bộ nhớ đã được phân bổ cho các ứng dụng". Vì vậy, điều này không thể được coi là rò rỉ bộ nhớ.

Tôi có đúng không?

+0

Chúng ta có nên giả định một ứng dụng đơn luồng không? –

+3

Hãy lấy một cái gì đó rõ ràng, 'ném;' trong mã của bạn tương đương với 'terminate()', bởi vì bạn đang cố gắng ném lại một ngoại lệ mà không có gì để ném lại. Nó được thực hiện xác định có hay không mà thư giãn ngăn xếp. Nếu bạn ném * một cái gì đó *, tất cả các biến tự động phải có destructors của họ được gọi là. Đó là toàn bộ ý tưởng đằng sau SBRM (RAII). – GManNickG

+0

jdv, vâng nó là một ứng dụng đơn luồng. – user373215

Trả lời

5

Trong một môi trường lưu trữ (ví dụ điển hình Unix/Windows/Mac OS X của bạn, ngay cả hệ điều hành DOS, máy) khi ứng dụng chấm dứt tất cả các bộ nhớ nó chiếm được tự động khai hoang bởi hệ điều hành. Vì vậy, nó không có ý nghĩa để lo lắng về rò rỉ bộ nhớ như vậy.

Trong một số trường hợp, trước khi ứng dụng chấm dứt, bạn có thể muốn giải phóng tất cả bộ nhớ động mà bạn đã cấp để phát hiện rò rỉ bộ nhớ tiềm năng thông qua thiết bị dò rò rỉ, như valgrind. Tuy nhiên, ngay cả trong trường hợp như vậy, ví dụ bạn mô tả sẽ không bị coi là rò rỉ bộ nhớ.

Nói chung, không gọi một destructor là không giống như gây rò rỉ bộ nhớ. Rò rỉ bộ nhớ xuất phát từ bộ nhớ được phân bổ trên heap (với các bộ cấp phát mới hoặc malloc hoặc container). Bộ nhớ được cấp phát trên ngăn xếp sẽ tự động được khôi phục khi ngăn xếp được mở. Tuy nhiên, nếu một đối tượng nắm giữ một số tài nguyên khác (nói một tập tin hoặc một cửa sổ xử lý), không gọi destructor của nó sẽ gọi một rò rỉ tài nguyên, mà cũng có thể là một vấn đề. Một lần nữa, hệ điều hành hiện đại sẽ đòi lại tài nguyên của họ khi một ứng dụng chấm dứt.

+0

Giải thích tuyệt vời. Cảm ơn. – user373215

+0

Giải thích cụ thể, nhưng như Dennis đã chỉ ra ở trên - một số tài nguyên có thể không được tự động khai hoang: ví dụ: chia sẻ các phân đoạn bộ nhớ, khóa trong đó, các tệp mà ứng dụng. thường sẽ xóa. –

2

Câu trả lời là, nó phụ thuộc vào hệ điều hành. Tôi không thể nghĩ về một hệ điều hành hiện đại mà không làm theo cách này. Nhưng các hệ thống cũ (tôi nghĩ sẽ giành được 3.1 trong các cửa sổ và một số nền tảng Linux nhúng cũ) nếu chương trình đóng mà không giải phóng các yêu cầu bộ nhớ, hệ điều hành sẽ giữ chúng cho đến khi bạn khởi động lại.

4

chỉnh sửa: như đã đề cập bởi GMAN, "ném"; tái ném một ngoại lệ đã ném trước đó, hoặc nếu không có ngoại lệ, ngay lập tức chấm dứt. Vì không có trường hợp nào trong trường hợp này, việc chấm dứt ngay lập tức là kết quả.

Chấm dứt một quy trình luôn dọn sạch mọi bộ nhớ còn lại của người dùng trong bất kỳ hệ điều hành hiện đại nào, do đó thường không bị coi là "rò rỉ bộ nhớ". Tuy nhiên, nó thực sự lên đến hệ điều hành là để cho dù một điều như vậy được coi là một "rò rỉ bộ nhớ".

+0

Có hay không các destructors được gọi là trong trường hợp này được thực hiện xác định, nhưng bạn thực hiện một đảm bảo. (Nó không ném bất kỳ ngoại lệ.) – GManNickG

+0

Trong trường hợp của tôi, destructor không được gọi. Vì vậy, tôi đã đăng câu hỏi. – user373215

+0

GMan là chính xác ... vì "ném" không ném bất kỳ ngoại lệ nào trong trường hợp này. "ném đi;" một mình lại ném một ngoại lệ đã ném trước đó mà bạn không có. Vì không có ngoại lệ ném trước đó, nó ngay lập tức chấm dứt. Vì vậy, cho dù đó là một "rò rỉ bộ nhớ" sau đó được xác định bởi hệ điều hành mà bạn đang chạy. Không có hệ điều hành nào hiện tại mà tôi biết không làm sạch bộ nhớ của quá trình chấm dứt, nhưng nó tùy thuộc vào hệ điều hành để ngăn chặn rò rỉ bộ nhớ trong trường hợp này. – samkass

1

rò rỉ bộ nhớ được coi là một vấn đề vì một ứng dụng dài chạy chậm sẽ chảy máu đi bộ nhớ hệ thống và có thể trong trường hợp tồi tệ nhất làm cho toàn bộ máy không sử dụng được do điều kiện bộ nhớ thấp. Trong trường hợp của bạn, ứng dụng chấm dứt và tất cả bộ nhớ được cấp phát cho ứng dụng sẽ được đưa trở lại hệ thống, vì vậy khó có vấn đề gì.

+0

Cảm ơn Deus. Câu trả lời tốt. – user373215

1

Câu hỏi thực sự là, "Lớp học của tôi có phân bổ bất kỳ bộ nhớ nào phải tự do/xóa không?"

Nếu không - nếu bộ nhớ duy nhất nó sử dụng là thành viên nội bộ - thì nó tồn tại hoàn toàn trên ngăn xếp. Một khi nó rời khỏi chức năng đó (tuy nhiên nó có), bộ nhớ trên ngăn xếp được khai hoang và tái sử dụng. myclass đã biến mất. Đó chỉ là cách ngăn xếp hoạt động.

Nếu lớp của tôi phân bổ bộ nhớ cần được giải phóng trong dtor của nó, thì bạn vẫn còn may mắn, vì dtor sẽ được gọi là ngăn xếp được bỏ trong khi ném. Các dtor sẽ đã được gọi trước khi ngoại lệ được tuyên bố unhandled và chấm dứt được gọi là.

Nơi duy nhất bạn sẽ gặp sự cố là nếu lớp của tôi có dtor, và dtor ném như ngoại lệ của nó. Ném thứ hai xảy ra trong ngăn xếp thư giãn từ ném đầu tiên sẽ có nó gọi là chấm dứt immedaitely mà không có bất kỳ dtors được gọi.

0

Sự hiểu biết của tôi là "Khi ứng dụng chấm dứt (hoặc bằng cách hủy bỏ hoặc bằng cách thoát bình thường), nó giải phóng tất cả bộ nhớ được cấp cho ứng dụng". Vì vậy, điều này không thể được coi là rò rỉ bộ nhớ.

Tôi có đúng không?

Rò rỉ bộ nhớ là loại lỗi lập trình được xếp hạng hơi thấp hơn trên quy mô lỗi lập trình - so với ngoại lệ chưa được nắm bắt.

IOW, nếu chương trình không chấm dứt đúng cách, lỗi a.k.a., thì còn quá sớm để nói về rò rỉ bộ nhớ. Một lưu ý khác, hầu hết các bộ phân tích bộ nhớ tôi đã làm việc trong thập kỷ qua sẽ không kích hoạt bất kỳ báo động rò rỉ bộ nhớ nào trong trường hợp - bởi vì chúng không kích hoạt bất kỳ báo động nào khi chương trình bị đổ vỡ một cách ngớ ngẩn. Đầu tiên phải làm cho chương trình không bị lỗi, chỉ sau đó gỡ lỗi rò rỉ bộ nhớ.

1

Từ OP,

Nếu ném không được xử lý, nó gọi, chấm dứt(), nó sẽ gọi hủy bỏ() và bị treo ứng dụng. Tại thời điểm này, các đối tượng trong ngăn xếp không phải là destoryed (The destructor là không được gọi).

Đây là hành vi được xác định thực hiện.

$ 15,3/9- "Nếu không xử lý phù hợp được tìm thấy trong một chương trình, chức năng chấm dứt() được gọi; hay không ngăn xếp được unwound trước khi cuộc gọi này chấm dứt() là thực hiện -defined (15.5.1). "

Vì vậy, dù điều này có thành phần rò rỉ bộ nhớ hay không cũng là hành vi được xác định thực hiện, tôi đoán vậy.

+0

Cảm ơn Chubsdad. Đó là một lời giải thích tốt. – user373215

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