2012-03-29 23 views
6

Từ các cuộc thảo luận bắt đầu here, tôi muốn biết liệu các mã sau đây có một rò rỉ bộ nhớ:Không gọi xóa trên một đối tượng được cấp phát động luôn luôn bị rò rỉ bộ nhớ?

int main() 
{ 
    new int(); 
    //or 
    int* x = new int(); 
    return 0; 
} 

Tôi biết bộ nhớ được khai hoang bởi hệ điều hành, nhưng nó là một sự rò rỉ không? Tôi tin rằng đó là.

Điều gì định nghĩa rò rỉ bộ nhớ? Tôi chỉ có thể tìm thấy một tài liệu tham khảo trong tiêu chuẩn, và nó không phải là rất hữu ích.

EDIT: Tôi không muốn bắt đầu một cuộc tranh luận - "Tôi nghĩ rằng ..." không phải là loại câu trả lời tôi đang tìm kiếm. Tôi chủ yếu quan tâm đến các nguồn - những cuốn sách hoặc trang web C++ hoặc bất kỳ điều gì phải nói về nó.

+3

Rò rỉ bộ nhớ chỉ đơn giản là bộ nhớ bạn phân bổ nhưng không miễn phí. –

+0

@ JoachimPileborg đó là những gì tôi đang nói trong cuộc thảo luận bị rò rỉ. James nói rằng đó là sự mất dần trí nhớ. Tôi không thể tìm thấy bất kỳ nguồn thỏa mãn nào. –

+0

@ Joachim quá đơn giản. Bộ nhớ phân bổ theo định nghĩa của bạn đã bị rò rỉ bộ nhớ –

Trả lời

1

Trường hợp thứ hai không phải là rò rỉ bộ nhớ.
Nó không phải là một rò rỉ bởi vì bạn vẫn có một con trỏ đến bộ nhớ đã được phân bổ.
Để xác định một rò rỉ bộ nhớ Tôi muốn dính vào định nghĩa mà hầu hết các công cụ phân tích bộ nhớ như sử dụng valgrind:

Memory được phân bổ và không thể sau đó trả tự do vì chương trình không còn có bất kỳ con trỏ vào bộ nhớ được phân bổ khối.

+1

+1 Tôi biết điều này, đó là lý do tại sao tôi đăng cả hai phiên bản. Vậy cái đầu tiên là, mặc dù nó không bị rò rỉ liên tục? –

+2

+1: Định nghĩa ngắn gọn, ngắn gọn: 'các đối tượng không thể truy cập được bằng mã đang chạy nhưng vẫn được lưu trong bộ nhớ ' –

+0

@LuchianGrigore: Tôi cố tình hạn chế nhận xét về kịch bản đầu tiên vì câu hỏi của bạn nói, *" Tôi nghĩ rằng ... không phải là loại câu trả lời tôi đang tìm kiếm "*. Vâng, kể từ khi bạn hỏi, tôi nghĩ rằng kịch bản đầu tiên là một rò rỉ, và tôi chắc chắn valgrind đồng ý nhưng sau đó một lần nữa nó chỉ có tôi và valgrind suy nghĩ, không phải một số tiêu chuẩn :) –

1

tôi sẽ xác định một bộ nhớ bị rò rỉ cách này

a) phải mất bộ nhớ

b) nó không hữu ích hơn cho các ứng dụng

c) nó không dễ tiếp cận hơn, và do đó không xóa được

Theo đó tôi sẽ đánh giá mẫu của bạn là rò rỉ bộ nhớ. Mẫu của bạn hiển thị rò rỉ không chính xác. Rò rỉ quan trọng là bộ nhớ liên tục, điều gì có thể xảy ra cho đến khi ứng dụng gặp sự cố

4

Đoạn mã trên thực sự bị rò rỉ. Tuy nhiên, quan trọng hơn, nếu bạn phân bổ một đối tượng đặc biệt, nói một đối tượng kết nối máy chủ, nếu bạn không bao giờ dọn dẹp và gọi delete, trình phá hủy của đối tượng sẽ không bao giờ chạy, điều này có thể quan trọng nếu nhu cầu kết nối máy chủ của bạn để thực hiện mã làm sạch đặc biệt (ghi vào tệp, v.v.).

Trong ví dụ cụ thể của bạn, rò rỉ là không có hậu quả kể từ khi thoát ra ngay lập tức chính (hiệu quả) và bộ nhớ được trả lại cho hệ điều hành. Tuy nhiên, bằng cách viết mã sản xuất, bạn chắc chắn không để lại bất kỳ rò rỉ nào (kể cả một trong những điều nhỏ nhặt như trên) vì mã có thể bị di chuyển xung quanh thành một hàm khác, và sự rò rỉ thực sự có thể tự lan truyền qua suốt thời gian của chương trình.

Ngoài ra, có lẽ điều quan trọng nhất cần xem xét là những gì bạn lập trình viên coi là rò rỉ bộ nhớ. Bạn nên xem xét bộ nhớ dưới dạng tài nguyên cần được quản lý theo mô hình của riêng bạn. Hãy xem xét đọc this article thảo luận về một số mô hình phân bổ và quản lý tài nguyên. Xem xét RAII (mua lại tài nguyên là khởi tạo) và con trỏ thông minh (hoặc ít nhất là ý tưởng của con trỏ thông minh và ý tưởng đếm tham chiếu).

+0

Ai đó muốn điền tôi vào -1? – Chris

+0

Tương tự ở đây. Tốt nhất cho chúng tôi để biết những gì là sai với câu trả lời của chúng tôi để chúng tôi có thể xóa/chỉnh sửa chúng nếu chúng không chính xác. –

+0

Không có tham chiếu đến những gì một rò rỉ bộ nhớ có nghĩa là. Không thực sự trả lời câu hỏi. –

-1

Có, bị rò rỉ 4 byte vì bộ nhớ được phân bổ bởi new không phải là delete d và trong suốt thời gian của ứng dụng, nó bị rò rỉ.

Từ liên kết này:

http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

Memory leak description: Memory is allocated but not released causing an application to consume memory reducing the available memory for other applications and eventually causing the system to page virtual memory to the hard drive slowing the application or crashing the application when than the computer memory resource limits are reached. The system may stop working as these limits are approached.

+0

Nhưng điều này - "gây ra một ứng dụng để tiêu thụ bộ nhớ giảm bộ nhớ có sẵn cho các ứng dụng khác" - không áp dụng. –

+0

Nếu có một ứng dụng rò rỉ bộ nhớ trong một vòng lặp và ứng dụng này đang chạy trong một khoảng thời gian dài hơn, hệ thống sẽ chậm lại. Tất nhiên điều đó phụ thuộc vào lượng bộ nhớ bị rò rỉ. Việc rò rỉ trong ví dụ của bạn sẽ không làm cho hệ thống bị chậm lại. – Sanish

+0

Tôi đã cung cấp cho bạn mã và không có vòng lặp nào ở đó. –

1

Đó là chủ quan/gây tranh cãi.

Theo ý kiến ​​của tôi, có hai cấp độ tài nguyên (bộ nhớ là một trong những tài nguyên được cung cấp bởi hệ điều hành) rò rỉ: Cấp hệ điều hành và cấp ứng dụng. Xin lưu ý rằng tên là tùy chỉnh và có thể có thuật ngữ kỹ thuật phù hợp hơn cho họ.

Ngừng cấp ứng dụng không còn tồn tại sau khi ứng dụng chấm dứt do ứng dụng dọn dẹp hệ điều hành của ứng dụng. I E. một khi ứng dụng được nuked, mối đe dọa đến sự ổn định hệ điều hành đã biến mất. Về phân bổ bộ nhớ hệ điều hành phong nha trong các ứng dụng chỉ có thể tạo ra rò rỉ "cấp ứng dụng".

Mức độ rò rỉ cấp hệ điều hành sẽ không ngừng tồn tại sau khi ứng dụng chấm dứt. Thông thường một số tài nguyên khác rơi vào danh mục đó (tệp), nhưng không phải bộ nhớ. Tuy nhiên, tôi không thể đảm bảo rằng không có hệ điều hành/nền tảng không dọn sạch bộ nhớ bị rò rỉ. Theo luật của murphy, có lẽ nền tảng này được sử dụng ngay cả ngày nay.

Vì vậy, khi tôi nói/viết "bộ nhớ bị rò rỉ" Tôi đang nói về mức ứng dụng bị rò rỉ - bất kỳ cấp phát bộ nhớ mà không bị xóa một cách rõ ràng bởi APP. Mỗi phân bổ, thậm chí có chủ ý, rơi vào thể loại. Ngoài ra, các trình thông báo cấp phát bộ nhớ thông thường và các công cụ tương tự sẽ khiếu nại về "các rò rỉ cố ý" của bạn,

Vì vậy, có, mã của bạn bị rò rỉ. Theo quan điểm của tôi, thậm chí khi bạn chắc chắn rằng hệ điều hành sẽ giải phóng chúng là một ý tưởng tồi vì nó khuyến khích mã hóa cẩu thả và một ngày bạn sẽ không xóa lớp phát hành thứ gì đó importan trong destructor không thể được dọn dẹp bởi hệ điều hành tự động. Với số lượng rác còn lại trong cửa sổ đăng ký và thư mục tệp tạm thời trên PC trung bình, nhiều người lập trình thường xuyên sử dụng kỹ thuật đó cho các tài nguyên không được hệ điều hành dọn dẹp đúng cách. Vì vậy, ý tưởng tốt nhất là tránh làm rò rỉ.

+0

Nếu bạn đang nói về tài nguyên nói chung (và không chỉ bộ nhớ), thì hệ điều hành không có khả năng dọn dẹp mọi thứ. Tệp tạm thời mà bạn không xóa là rò rỉ tài nguyên sẽ không bị hệ điều hành làm sạch. (Đối với phần còn lại, bạn đã phát minh ra một định nghĩa hoàn toàn mới và vô dụng của từ "rò rỉ".) –

5

Tùy thuộc vào cách bạn xác định "rò rỉ". Theo định nghĩa rõ ràng nhất và định nghĩa hữu ích nhất, nó không phải là rò rỉ, ít nhất là ở mức ứng dụng . Thùng không bị rò rỉ vì bạn cố tình cho phép một lượng nước hữu hạn thoát ra ngoài. Và thực tế nói, một ứng dụng không thành công vì bạn cố ý cho phép một tập hợp ràng buộc của các đối tượng tồn tại ngoài phần cuối của chương trình.

Liên quan đến rò rỉ bộ nhớ, nhận thức của chúng tôi về từ đã được tô màu bởi "bộ kiểm tra rò rỉ" --- các chương trình như Purify hoặc Valgrind. Vai trò của họ là tìm rò rỉ (trong số những thứ khác), nhưng họ không có cách nào để biết điều gì là cố ý và cái gì không, và những gì bị ràng buộc, và những gì thì không. Vì vậy, họ phát minh ra các định nghĩa khác: một đối tượng không thể truy cập được đã "bị rò rỉ" (và có một xác suất tốt trong mã thực sự là đúng) hoặc đối tượng chưa bị xóa sau khi tất cả các đối tượng tĩnh của các đối tượng tĩnh bị được thực hiện đã "bị rò rỉ".Trong trường hợp sau này, định nghĩa rõ ràng là sai và loại vô dụng. Nhưng có đủ trường hợp những thứ như vậy bị rò rỉ mà nó là hợp lý để ít nhất cảnh báo về chúng ("rò rỉ có thể"), được cung cấp có một cách để lọc ra các trường hợp cụ thể. (Cả hai Purify và Valgrind nhận ra rằng không phải tất cả các trường hợp này đều thực sự bị rò rỉ, và cung cấp nhiều cơ chế lọc khác nhau để phát hiện.) Tất cả đều là tốt và tốt — Tôi rất vui vì chúng tôi có các công cụ như vậy — nhưng chúng ta không nên cho phép họ làm hỏng ngôn ngữ.

Và một lời nhắc cuối cùng: tiêu chuẩn cho biết các tiêu chuẩn iostream đối tượng (std::cout, v.v.) sẽ không bao giờ bị hủy. Vì vậy, bất kỳ bộ đệm nào chúng phân bổ sẽ (có thể) không bao giờ được giải phóng. Chắc chắn không ai trong tâm trí phải của họ sẽ xem xét những "rò rỉ".

+1

Đây chắc chắn là một điểm thú vị, không bao giờ nghĩ về kịch bản * rò rỉ hữu hạn *, nhưng nó có ý nghĩa. Tôi cảm thấy chứng ngộ. –

+0

@MatthieuM. Từ quan điểm thực dụng, vấn đề "ràng buộc" có vẻ quan trọng đối với tôi. Và nó phù hợp với những gì tôi trực giác nghĩ đến như là một "rò rỉ" trong bối cảnh không lập trình. Nhưng việc kiểm tra với Merriam-Webster cho thấy rằng ngay cả trong bối cảnh không lập trình, nó cũng không rõ ràng. –

+0

Thuật ngữ "rò rỉ" có thể hàm ý cả hai trường hợp bị chặn và không bị chặn, trong ngữ cảnh lập trình và phi lập trình. Thực tế là chỉ có năm gallon chất lỏng có thể thoát ra từ một cái lỗ trong một cái xô năm gallon không có nghĩa là lỗ không phải là "rò rỉ". Và nếu các đối tượng sẽ tiếp tục tồn tại vô ích sau khi thoát khỏi chương trình, chúng sẽ bị rò rỉ. Mặt khác, nếu chạy chương trình một lần nữa sẽ làm cho các đối tượng được tái sử dụng, chúng thực tế là chúng có thể tái sử dụng có nghĩa là chúng không phải là "vô dụng". Và nếu hệ điều hành sẽ làm sạch chúng trước khi chúng gây ra vấn đề, chúng sẽ không bị rò rỉ. – supercat

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