2010-09-10 45 views
14

Xin lỗi vì phạm vi câu hỏi rộng lớn. Nhưng yếu tố thiết kế trong việc quản lý bộ nhớ trong C++ là gì? Ví dụ: tại sao có rò rỉ bộ nhớ khi một chương trình không phát hành một đối tượng bộ nhớ trước khi nó thoát ra? Không phải là một thiết kế ngôn ngữ lập trình tốt phải duy trì một "foo-bảng" mà sẽ chăm sóc tình trạng này? Tôi biết tôi là một chút ngây thơ, nhưng triết lý thiết kế của quản lý bộ nhớ trong C + + đối với các lớp học, cấu trúc, phương pháp, giao diện, các lớp trừu tượng là gì?Triết lý quản lý bộ nhớ trong C++ là gì?

Chắc chắn một người không thể nhớ mọi thông số của C++. Thiết kế lái xe lõi của quản lý bộ nhớ là gì?

+0

Bạn có thể quan tâm đến http://stackoverflow.com/questions/3289726/in-c-any-general-guidelines-for-handling-memory-allocation-deletion/3289929 – sellibitze

Trả lời

37

Thiết kế lái xe lõi của quản lý bộ nhớ là gì?

Trong hầu hết các trường hợp, bạn nên sử dụng quản lý tài nguyên tự động. Về cơ bản:

  • Bất cứ nơi nào nó là thực tế để làm như vậy, thích tạo các đối tượng với thời gian lưu trữ tự động (có nghĩa là, trên stack, hoặc chức năng địa phương)
  • Bất cứ khi nào bạn phải sử dụng phân bổ năng động, sử dụng Phạm vi-bound Quản lý tài nguyên (SBRM; thường được gọi là Resource Acquisition is Initialization hoặc RAII).

Hiếm khi làm bạn phải viết chứa RAII riêng bạn: thư viện chuẩn C++ cung cấp một tập hợp toàn bộ container (ví dụ, vectormap) và con trỏ thông minh như shared_ptr (từ C++ TR1, C++ 0x, và Boost) hoạt động rất tốt cho các tình huống phổ biến nhất. Về cơ bản, trong mã C++ thực sự tốt, bạn không bao giờ nên tự gọi delete mình để dọn bộ nhớ mà bạn đã cấp: quản lý bộ nhớ và dọn dẹp tài nguyên phải luôn được đóng gói trong một vùng chứa nào đó.

1. Rõ ràng, ngoại lệ ở đây là khi bạn tự mình triển khai vùng chứa RAII, vì vùng chứa đó phải chịu trách nhiệm làm sạch bất cứ thứ gì mà nó sở hữu.

+0

ngay cả khi tự mình thực hiện thùng chứa SBRM, Tôi thường thích dựa vào 'unique_ptr' hoặc' scoped_ptr'. Dễ dàng hơn nhiều. Cũng không nên quên thư viện Boost Pointer Container xuất sắc, không cần thiết với 'unique_ptr', nhưng vẫn cung cấp thêm khả năng:' clone' và cú pháp đường với toán tử. –

+1

+1 "bạn không bao giờ nên tự xóa mình": Điều này rất đúng nhưng thường bị hiểu lầm. Tôi thường nghe lời buộc tội: C + + chưa có một người thu gom rác. Nếu người ta tuân theo các hướng dẫn mà bạn liệt kê, thì một người thu gom rác thải phần lớn là không cần thiết. –

+0

Khi sử dụng thời lượng lưu trữ tự động bằng cách sử dụng Ngăn xếp, có bất kỳ giới hạn nào đối với kích thước dữ liệu của tôi mà tôi có thể lưu trữ hay không. Tôi có thể thêm một triệu đối tượng của lớp "Person" vào đối tượng của lớp "Nation" không? Điều gì hạn chế kích thước của không gian đối tượng trong ngăn xếp để tránh tràn bộ đệm ?? –

2

tại sao có rò rỉ bộ nhớ khi chương trình không phát hành đối tượng bộ nhớ trước khi thoát?

Vâng, hệ điều hành thường dọn dẹp mớ hỗn độn của bạn cho bạn. Tuy nhiên, điều gì sẽ xảy ra khi chương trình của bạn chạy trong một khoảng thời gian tùy ý và bạn đã tiết lộ quá nhiều bộ nhớ mà bạn không thể phân bổ nữa? Bạn sụp đổ, và điều đó không tốt.

Không phải là thiết kế ngôn ngữ lập trình tốt phải duy trì "bảng foo" để xử lý tình huống này?

No. Một số ngôn ngữ lập trình có quản lý bộ nhớ tự động, một số ngôn ngữ thì không. Có những lợi ích và hạn chế đối với cả hai mô hình. Ngôn ngữ với quản lý bộ nhớ thủ công cho phép bạn nói khi nào và ở đâu tài nguyên được phân bổ và phát hành, tức là, nó rất xác định. Tuy nhiên, một người mới bắt đầu tương đối chắc chắn sẽ viết mã bị rò rỉ trong khi họ đang quen với việc quản lý bộ nhớ.

Đề án tự động rất tuyệt vời cho lập trình viên, nhưng bạn không có cùng một mức độ xác định. Nếu tôi viết một trình điều khiển phần cứng, đây có thể không phải là một mô hình tốt cho tôi.Nếu tôi đang viết một GUI đơn giản, thì có lẽ tôi không quan tâm đến một số đối tượng tồn tại lâu hơn một chút so với những gì họ cần, vì vậy tôi sẽ thực hiện một chương trình quản lý tự động mỗi lần. Điều đó không có nghĩa là các ngôn ngữ GC chỉ dành cho các nhiệm vụ 'đơn giản', một số nhiệm vụ chỉ yêu cầu kiểm soát chặt chẽ hơn đối với tài nguyên của bạn. Không phải tất cả các nền tảng đều có bộ nhớ 4GB + để bạn chơi xung quanh).

Có các mẫu mà bạn có thể sử dụng để giúp bạn quản lý bộ nhớ. Ví dụ kinh điển sẽ là RAII (Resource Allocation is Initialization)

+0

Có Sir !! bạn đúng rồi. Nhưng tại sao một tình huống như vậy được một ngôn ngữ lập trình cho phép. Thiết kế này có chủ ý để làm cho các lập trình viên mạnh mẽ hay hoang tưởng về mọi phân bổ bộ nhớ được tạo ra không ?? –

+0

Đã thêm thông tin. –

+1

@de costo: Không, đó là nhiều hơn rằng có một thời gian khi đó "điều huyền diệu" được gọi là một bộ thu rác không tồn tại. –

3

C và C++ lấy vị trí mà bạn, lập trình viên, biết khi nào bạn đã xong với bộ nhớ bạn đã cấp phát. Điều này tránh sự cần thiết cho thời gian chạy ngôn ngữ để biết nhiều về bất cứ điều gì đã được phân bổ, và các nhiệm vụ liên quan (đếm tham chiếu, thu gom rác thải, vv) cần thiết để "dọn sạch" khi cần thiết.

Tại điểm mấu chốt là ý tưởng rằng: nếu bạn phân bổ nó, bạn phải giải phóng nó. (malloc/miễn phí, mới/xóa)

Có một số phương pháp giúp quản lý việc này để bạn không phải nhớ rõ ràng. RAII và việc triển khai con trỏ thông minh cung cấp các thùng chứa làm việc đó cực kỳ hữu ích và mạnh mẽ để quản lý bộ nhớ dựa trên việc tạo và phá hủy đối tượng. Họ sẽ giúp bạn tiết kiệm thời gian.

4

Nó không hoàn toàn rõ ràng cho dù bạn đang hỏi về triết lý của những gì được xây dựng vào C + +, hoặc làm thế nào để sử dụng nó theo cách ngăn chặn rò rỉ bộ nhớ.

Cách chính để ngăn rò rỉ bộ nhớ (và các rò rỉ tài nguyên khác) được gọi là RAII (Khởi tạo tài nguyên là khởi tạo) hoặc SBRM (Quản lý tài nguyên phạm vi giới hạn). Dù bằng cách nào, ý tưởng cơ bản cũng khá đơn giản: vì các đối tượng có thời lượng lưu trữ là auto sẽ tự động bị hủy khi thoát khỏi phạm vi của chúng, bạn cấp phát bộ nhớ trong ctor của đối tượng đó và giải phóng bộ nhớ trong dtor của nó.

Theo như bản thân C++, nó không thực sự có một triết lý. Nó cung cấp các cơ chế, nhưng để nó cho lập trình viên để quyết định cơ chế nào phù hợp với tình huống trong tầm tay. Đó thường là RAII. Đôi khi nó có thể là một nhà sưu tập rác. Tuy nhiên, những lúc khác, nó có thể là các loại quản lý bộ nhớ tùy chỉnh khác nhau. Tất nhiên, đôi khi nó là sự kết hợp của hai hoặc cả ba thứ đó, hay cái gì khác hoàn toàn.

Chỉnh sửa: Với lý do tại sao C++ thực hiện mọi việc theo cách này, nó khá đơn giản: gần như bất kỳ lựa chọn nào khác sẽ khiến ngôn ngữ không phù hợp với ít nhất một số vấn đề - bao gồm số C++ thích hợp. Một trong những điều rõ ràng nhất trong số này là có thể chạy trên máy "trần" với cấu trúc hỗ trợ tối thiểu (ví dụ, không có hệ điều hành)

+0

+1 - lưu ý rằng việc phân bổ không nhất thiết phải xảy ra trong hàm tạo; xem 'std :: auto_ptr' cho một ví dụ mà nó không có. –

1

Triết lý, tôi nghĩ có hai điều dẫn đến C++ không có người thu gom rác (mà có vẻ là những gì bạn đang nhận được tại):

  • tương thích với C. C++ cố gắng rất tương thích với C, cho tốt hơn hoặc tồi tệ hơn. C không có bộ sưu tập rác, vì vậy C++ không, ít nhất là không theo mặc định. Tôi đoán bạn có thể tổng hợp điều này là "lý do lịch sử".

  • Triết lý "bạn chỉ trả tiền cho những gì bạn sử dụng". C++ cố gắng tránh áp đặt bất kỳ chi phí nào trên C trừ khi bạn yêu cầu một cách rõ ràng. Vì vậy, bạn chỉ trả giá ngoại lệ nếu bạn thực sự ném một, v.v. Có một lý lẽ rằng việc thu gom rác sẽ áp đặt chi phí bất cứ khi nào một đối tượng được cấp phát trên heap để nó không thể là hành vi mặc định trong C++.

    Lưu ý rằng thực sự có khá nhiều tranh luận về việc liệu việc thu gom rác thực sự hiệu quả hơn hoặc ít hơn so với quản lý bộ nhớ thủ công. Các trình thu gom rác tốt hơn thường muốn có thể di chuyển các thứ xung quanh, và C++ có số học con trỏ (một lần nữa, được kế thừa từ C), làm cho nó rất khó để làm cho trình thu thập như vậy làm việc với C++.

Dưới đây là Stroustrup (không phải thực sự trực tiếp) câu trả lời cho "Why doesn't C++ have garbage collection?":

Nếu bạn muốn thu gom rác thải tự động, có tốt thương mại và công miền người thu gom rác cho C++. Đối với các ứng dụng nơi thu gom rác phù hợp, C++ là một ngôn ngữ thu thập rác tuyệt vời với hiệu suất so sánh thuận lợi với các ngôn ngữ thu gom rác khác. Xem Ngôn ngữ lập trình C++ (Phiên bản thứ 3) để thảo luận về thu gom rác tự động trong C++. Xem thêm, Hans-J. Trang web của Boehm về thu gom rác C và C++.

Ngoài ra, C++ hỗ trợ các kỹ thuật lập trình cho phép quản lý bộ nhớ an toàn và ẩn mà không cần bộ thu gom rác.

C++ 0x cung cấp GC ABI.

0

Thiết kế lái xe lõi của quản lý bộ nhớ là gì?

Thiết kế lái xe (không có ý định chơi chữ) hơi giống với ô tô truyền dính thay vì ô tô truyền tự động. Giống như một chiếc xe thay đổi thanh, C++ mang đến cho bạn sự tự do và kiểm soát máy, nhưng nó không dễ sử dụng như những chiếc tự động giúp bạn chăm sóc nhiều thứ.

Sau đây có thể dễ dàng đã được viết về C++ so với Java:

Những người lái xe thanh ca xe biết sự khác biệt và những ưu điểm của có toàn quyền kiểm soát của động cơ xe của bạn; những người lái xe ô tô tự động không được truyền. (...) Ví dụ: xe đua không sử dụng hộp số tự động . (...) Những người được sử dụng để chuyển bánh răng sẽ tập trung hơn vào việc thúc đẩy họ làm cho nó hiệu quả hơn và an toàn hơn.

http://www.eslbee.com/contrast_stick_shift_or_automatic.htm

tôi nên thêm, mặc dù, rằng C++ có một số cơ chế xử lý bộ nhớ cho bạn, như những người khác đã đề cập, ví dụ RAII, con trỏ thông minh, v.v.

-2

C++ không có bộ nhớ triết lý thiết kế. Tất cả nó có hai chức năng để cấp phát bộ nhớ (new malloc) và hai hàm để giải phóng bộ nhớ (xóa miễn phí) và một hàm liên quan đến frew. Ngay cả những người có thể được thay thế bởi các lập trình viên.

Điều này là do C++ nhằm chạy trên các máy tính chung. Các máy tính chung là một CPU, bộ nhớ (RAM, các kiểu ROM) và một bus/bus cho các thiết bị ngoại vi. Không có quản lý bộ nhớ trong máy tính chung.

Bây giờ hầu hết các máy tính đều có bộ nhớ (thường là một biến thể ROM) có chứa bios/màn hình. Ở đó bạn có thể thấy một số hình thức thô sơ của quản lý bộ nhớ - có thể không.

Một số máy tính đi kèm với hệ điều hành sẽ có bộ nhớ quản lý, nhưng ngay cả ở đó nó thường là nguyên thủy, và nó rất dễ dàng cho tôi để tuyên bố rằng hầu hết các máy tính chạy một chương trình C + + không có hệ điều hành nào cả.

Nếu bạn mong đợi C++ chạy trên bất kỳ máy tính nào, nó không thể có triết lý quản lý bộ nhớ.

+0

Vâng, 'new' và' delete' là toán tử, chứ không phải hàm, C++ cung cấp nhiều thứ hơn để quản lý bộ nhớ (về 'std :: string'?) Và quản lý bộ nhớ không phải là tính năng của hệ điều hành, nhưng môi trường thời gian chạy của một ngôn ngữ. – sbi

1

Không phải là thiết kế ngôn ngữ lập trình tốt phải duy trì "bảng foo" để xử lý tình huống này?

Có phải không? tại sao? Một ngôn ngữ lập trình tốt là một ngôn ngữ cho phép bạn giải quyết vấn đề, không còn nữa, không kém. Một bộ thu gom rác chắc chắn làm giảm rào cản nhập cảnh, nhưng nó cũng mất kiểm soát khỏi lập trình viên, mà có thể là một vấn đề trong một số trường hợp. Đúng, trên một máy tính quad-core 2.5GHz hiện đại, và với những người thu gom rác tiên tiến và hiệu quả ngày nay, chúng ta có thể sống với điều đó. Nhưng C++ đã phải làm việc với phần cứng hạn chế hơn nhiều, từ máy tính để bàn với 16MB bộ nhớ RAM xuống đến các nền tảng nhúng với 16KB và mọi thứ ở giữa. Nó phải có thể sử dụng được trong mã thời gian thực, nơi bạn có thể không chỉ cần tạm dừng chương trình trong 0,5 giây để chạy bộ sưu tập rác.

C++ không chỉ được thiết kế làm ngôn ngữ được sử dụng trên máy tính để bàn. Nó có nghĩa là có thể sử dụng được ở mọi nơi, trên các hệ thống có bộ nhớ hạn chế, trong các tình huống thời gian thực cứng, trên các siêu máy tính lớn và ở mọi nơi khác.

Nguyên tắc hướng dẫn của C++ là "bạn không trả tiền cho những gì bạn không sử dụng". Nếu bạn không muốn một bộ thu gom rác, bạn không cần phải trả giá (dốc) của một.

Có các kỹ thuật rất mạnh để quản lý bộ nhớ trong C++ và tránh rò rỉ bộ nhớ, ngay cả khi không có bộ thu gom rác. Nếu một người thu gom rác là chỉ cách để tránh rò rỉ bộ nhớ, thì sẽ có một đối số mạnh mẽ có lợi cho việc thêm một ngôn ngữ vào ngôn ngữ đó. Nhưng không phải vậy. Bạn chỉ cần học cách tự quản lý bộ nhớ trong C++.

+0

Bạn có thể liệt kê các kỹ thuật mạnh mẽ để quản lý bộ nhớ trong C++ để tránh rò rỉ bộ nhớ ngoài những kỹ thuật được liệt kê ở trên? –