Có bao giờ được phép * không * sử dụng free () trên bộ nhớ được cấp phát không?


83

Tôi đang học kỹ thuật máy tính và tôi có một số khóa học về điện tử. Tôi nghe nói, từ hai giáo sư của tôi (của các khóa học này) mà chúng ta có thể tránh sử dụng các free()chức năng (sau khi malloc(), calloc()vv) vì không gian bộ nhớ được phân bổ nhiều khả năng sẽ không được sử dụng lại để cấp phát bộ nhớ khác. Đó là, ví dụ, nếu bạn phân bổ 4 byte và sau đó giải phóng chúng, bạn sẽ có 4 byte không gian có khả năng sẽ không được phân bổ lại: bạn sẽ có một lỗ hổng .

Tôi nghĩ điều đó thật điên rồ: bạn không thể có một chương trình không-phải-đồ chơi mà bạn phân bổ bộ nhớ trên heap mà không giải phóng nó. Nhưng tôi không có kiến ​​thức để giải thích chính xác lý do tại sao nó quan trọng đến mức đối với mỗi cái malloc()phải có một free().

Vì vậy: có bao giờ trường hợp nào thích hợp để sử dụng a malloc()mà không sử dụng free()không? Và nếu không, làm thế nào tôi có thể giải thích điều này với các giáo sư của tôi?


11
Chúng không "sai" - chúng có quan điểm hợp lệ (nếu có giới hạn) về sự phân mảnh của các vùng tự do rất nhỏ bị cô lập và có thể đã nêu nó cẩn thận hơn một chút so với những gì bạn đã báo cáo.
Chris Stratton

2
Lần duy nhất bạn không cần giải phóng bộ nhớ là khi sử dụng bộ nhớ được quản lý hoặc khi bạn định sử dụng lại bộ nhớ được cấp phát ban đầu. Tôi nghi ngờ rằng lý do hai người hướng dẫn nói điều này là vì bạn đang nói về một chương trình cụ thể có thể tái sử dụng bộ nhớ. Trong trường hợp này, bạn vẫn sẽ sử dụng free () nhưng chỉ ở cuối ứng dụng của mình. Bạn có chắc rằng đây không phải là ý nghĩa của chúng?
krowe

17
@Marian: Tôi đã có một giáo sư khẳng định rằng trong C và C ++, cần phải giải phóng bộ nhớ được cấp phát của bạn trong một hàm được xác định trong cùng một tệp .c / .cxx như nó đã được cấp phát ... Những người này đôi khi dường như bị thiếu oxy nghiêm trọng do sống quá cao trong tháp ngà.
PlasmaHH

4
Có khá một vài chương trình không đồ chơi mà không làm thu hồi bộ nhớ, và cho phép hệ điều hành làm sạch tất cả lên trên quá trình thoát là nhiều nhanh hơn (làm om sòm) giữ nhiều sổ sách kế toán, do đó bạn có thể làm điều đó cho mình.
Donal Fellows

9
Đừng bao giờ kết hợp những thứ bạn đã nghe vào bộ não của bạn mà không cần nghi ngờ. Tôi đã có nhiều giáo viên, người giảng và người sửa sai hoặc lỗi thời. Và luôn luôn phân tích những gì họ nói rất chính xác. Dân gian của chúng tôi thường khá chính xác và có thể nói những điều đúng, nhưng rất dễ hiểu sai hoặc có mức độ ưu tiên sai bởi một người cảm thấy chỉ ở nhà theo cách nói thông thường. Ví dụ, tôi nhớ ở trường, một giáo viên nói "Bạn đã làm bài tập về nhà của bạn.", Tôi nói "Không." Trong khi tôi nói đúng, thầy giáo thấy điều này khó chịu, vì tôi đã tiết kiệm thời gian cho tôi để tìm những lời bào chữa khập khiễng, điều mà thầy không ngờ tới.
Sebastian Mach

Câu trả lời:


100

Dễ dàng: chỉ cần đọc nguồn của khá nhiều cách malloc()/free()triển khai nửa chừng nghiêm túc . Ý tôi là trình quản lý bộ nhớ thực tế xử lý công việc của các cuộc gọi. Điều này có thể nằm trong thư viện thời gian chạy, máy ảo hoặc hệ điều hành. Tất nhiên mã không thể truy cập như nhau trong mọi trường hợp.

Đảm bảo bộ nhớ không bị phân mảnh, bằng cách ghép các lỗ liền kề thành các lỗ lớn hơn, rất phổ biến. Các nhà phân bổ nghiêm túc hơn sử dụng các kỹ thuật nghiêm túc hơn để đảm bảo điều này.

Vì vậy, giả sử bạn thực hiện ba phân bổ và khử phân bổ và nhận các khối được sắp xếp trong bộ nhớ theo thứ tự sau:

+-+-+-+
|A|B|C|
+-+-+-+

Kích thước của các phân bổ riêng lẻ không quan trọng. thì bạn giải phóng cái đầu tiên và cái cuối cùng, A và C:

+-+-+-+
| |B| |
+-+-+-+

khi cuối cùng bạn giải phóng được B, bạn (ban đầu, ít nhất là trên lý thuyết) kết thúc với:

+-+-+-+
| | | |
+-+-+-+

có thể được tách rời thành

+-+-+-+
|     |
+-+-+-+

tức là một khối tự do lớn hơn duy nhất, không còn mảnh nào.

Tài liệu tham khảo, theo yêu cầu:

  • Hãy thử đọc mã cho dlmalloc . Tôi đã tiến bộ hơn rất nhiều, là người thực hiện đầy đủ chất lượng sản xuất.
  • Ngay cả trong các ứng dụng nhúng, triển khai khử phân mảnh cũng có sẵn. Ví dụ, hãy xem những ghi chú này trên heap4.cmã trong FreeRTOS .

1
Bạn có thể cung cấp cho tôi một số tài liệu tham khảo?
Nick

4
Tôi nghĩ, điều đáng nói là không gian địa chỉ ảo không phải là đại diện trực tiếp của bộ nhớ vật lý. Và sự phân mảnh đó trong bộ nhớ vật lý có thể được xử lý bởi hệ điều hành, trong khi bộ nhớ ảo không được giải phóng theo quy trình cũng sẽ không được giải phóng vật lý.
lapk

@PetrBudnik nó sẽ là hiếm hoi mà bộ nhớ ảo ánh xạ 1-1 vào bộ nhớ vật lý dù sao, hệ điều hành sẽ nghĩ trong ánh xạ trang và có thể trao đổi nó vào và ra với tối thiểu phiền phức
quái ratchet

3
Nhận xét rất khó hiểu: Trong khi khái niệm được giải thích rõ ràng, ví dụ thực tế đã được chọn một chút .. không may mắn. Đối với bất kỳ ai nhìn vào mã nguồn của say dlmalloc và cảm thấy bối rối: Các khối dưới một kích thước cụ thể luôn là lũy thừa của 2 và được hợp nhất / tách theo đó. Vì vậy, chúng tôi sẽ kết thúc (có thể) với một khối 8 byte và 1 khối 4 byte, nhưng không có khối 12 byte. Đó là một cách tiếp cận khá tiêu chuẩn cho các trình phân bổ, ít nhất là trên máy tính để bàn, mặc dù có thể các ứng dụng nhúng cố gắng cẩn thận hơn với chi phí của chúng.
Voo

@Voo Tôi đã xóa đề cập đến kích thước cho các khối trong ví dụ, dù sao thì điều đó cũng không quan trọng. Tốt hơn?
thư giãn

42

Các câu trả lời khác đã giải thích một cách hoàn hảo rằng việc triển khai thực sự malloc()free()thực sự kết hợp các lỗ (defragmnent) thành các khối tự do lớn hơn. Nhưng ngay cả khi không phải như vậy, bạn vẫn nên từ bỏ free().

Vấn đề là, chương trình của bạn chỉ cấp phát (và muốn giải phóng) 4 byte bộ nhớ đó. Nếu nó chạy trong một khoảng thời gian dài, rất có thể nó sẽ chỉ cần cấp phát lại 4 byte bộ nhớ. Vì vậy, ngay cả khi 4 byte đó sẽ không bao giờ kết hợp thành một không gian liền kề lớn hơn, chúng vẫn có thể được sử dụng lại bởi chính chương trình.


6
+1 Chính xác. Vấn đề là, nếu freeđược gọi đủ thời gian để có tác động đến hiệu suất, thì nó có lẽ cũng được gọi là đủ thời gian để bỏ nó đi sẽ tạo ra một khoảng trống rất lớn trong bộ nhớ khả dụng. Thật khó để tưởng tượng một tình huống trên một hệ thống nhúng mà hiệu suất liên tục bị ảnh hưởng bởi freenhưng nơi mallocchỉ được gọi là một số lần hữu hạn; Đây là một trường hợp sử dụng khá hiếm khi có một thiết bị nhúng thực hiện xử lý dữ liệu một lần sau đó đặt lại.
Jason C

10

Nó hoàn toàn vô lý, ví dụ như có nhiều cách triển khai khác nhau malloc, một số cố gắng làm cho heap hiệu quả hơn như của Doug Lea hoặc cái này .


9

Các giáo sư của bạn có đang làm việc với POSIX không? Nếu họ đã quen với việc viết nhiều ứng dụng shell nhỏ, tối giản, thì đó là một kịch bản mà tôi có thể tưởng tượng rằng cách tiếp cận này sẽ không quá tệ - giải phóng toàn bộ đống cùng một lúc với hệ điều hành nhanh hơn giải phóng một nghìn biến. Nếu bạn mong đợi ứng dụng của mình chạy trong một hoặc hai giây, bạn có thể dễ dàng thoát ra mà không cần hủy phân bổ.

Tất nhiên, đó vẫn là một thực tiễn tồi (việc cải thiện hiệu suất luôn phải dựa trên việc lập hồ sơ chứ không phải cảm giác mơ hồ) và đó không phải là điều bạn nên nói với sinh viên mà không giải thích các ràng buộc khác, nhưng tôi có thể hình dung ra rất nhiều thứ -Ứng dụng được viết theo cách này (nếu không sử dụng hoàn toàn cấp phát tĩnh). Nếu bạn đang làm việc trên một thứ gì đó có lợi từ việc không giải phóng các biến của mình, thì hoặc bạn đang làm việc trong điều kiện độ trễ cực thấp (trong trường hợp đó, làm thế nào bạn có thể đủ khả năng phân bổ động và C ++?: D), hoặc bạn làm điều gì đó rất, rất sai (như cấp phát một mảng số nguyên bằng cách cấp phát lần lượt một nghìn số nguyên thay vì một khối bộ nhớ).


Để hệ điều hành giải phóng mọi thứ cuối cùng không chỉ là về hiệu suất - nó cũng cần ít logic hơn nhiều để hoạt động.
ômomg

@missingno Nói cách khác, nó cho phép bạn thoát khỏi việc quản lý bộ nhớ khó khăn như thế nào :) Tuy nhiên, tôi sẽ xem đó là một lập luận chống lại các ngôn ngữ không được quản lý - nếu lý do của bạn là logic giải phóng phức tạp hơn là hiệu suất, bạn có thể tốt hơn tắt sử dụng ngôn ngữ / môi trường chăm sóc nó cho bạn.
Luaan

5

Bạn đã đề cập họ là giáo sư điện tử. Họ có thể đã quen với việc viết phần mềm chương trình cơ sở / thời gian thực, có thể định thời gian chính xác việc thực thi một thứ gì đó thường là cần thiết. Trong những trường hợp đó, biết rằng bạn có đủ bộ nhớ cho tất cả các lần phân bổ và không giải phóng và phân bổ lại bộ nhớ có thể đưa ra giới hạn thời gian thực thi dễ tính hơn.

Trong một số chương trình, bảo vệ bộ nhớ phần cứng cũng có thể được sử dụng để đảm bảo quy trình hoàn thành trong bộ nhớ được cấp phát của nó hoặc tạo ra một cái bẫy trong những trường hợp rất đặc biệt.


10
Đó là một điểm hay. Tuy nhiên, tôi hy vọng rằng họ sẽ không sử dụng mallocvà tương tự trong trường hợp đó, thay vào đó dựa vào phân bổ tĩnh (hoặc có thể phân bổ một đoạn lớn và sau đó xử lý bộ nhớ theo cách thủ công).
Luaan

2

Nhìn nhận điều này từ một góc độ khác với những người bình luận và trả lời trước đó, một khả năng là các giáo sư của bạn đã có kinh nghiệm với các hệ thống mà bộ nhớ được cấp phát tĩnh (ví dụ: khi chương trình được biên dịch).

Phân bổ tĩnh xuất hiện khi bạn làm những việc như:

define MAX_SIZE 32
int array[MAX_SIZE];

Trong nhiều hệ thống thời gian thực và hệ thống nhúng (những hệ thống mà EE hoặc CE thường gặp nhất), thường nên tránh hoàn toàn việc cấp phát bộ nhớ động. Vì vậy, việc sử dụng malloc,new và các đối tác xóa của họ là rất hiếm. Hơn hết, bộ nhớ trong máy tính đã bùng nổ trong những năm gần đây.

Nếu bạn có sẵn 512 MB cho bạn và bạn phân bổ tĩnh 1 MB, bạn có khoảng 511 MB để xử lý trước khi phần mềm của bạn phát nổ (tốt, không chính xác ... nhưng hãy đi với tôi ở đây). Giả sử bạn có 511 MB để lạm dụng, nếu bạn phân bổ 4 byte mỗi giây mà không giải phóng chúng, bạn sẽ có thể chạy gần 73 giờ trước khi hết bộ nhớ. Xem xét nhiều máy tắt mỗi ngày một lần, điều đó có nghĩa là chương trình của bạn sẽ không bao giờ hết bộ nhớ!

Trong ví dụ trên, rò rỉ là 4 byte mỗi giây, hoặc 240 byte / phút. Bây giờ hãy tưởng tượng rằng bạn giảm tỷ lệ byte / phút đó. Tỷ lệ đó càng thấp, chương trình của bạn có thể chạy lâu hơn mà không gặp sự cố. Nếu là của bạnmalloc s không thường xuyên, đó là một khả năng thực sự.

Rất tiếc, nếu bạn biết rằng bạn chỉ đi đến mallocmột thứ gì đó một lần và điều đó mallocsẽ không bao giờ xảy ra nữa, thì nó giống như phân bổ tĩnh, mặc dù bạn không cần biết kích thước của nó mà bạn đang phân bổ- trước mặt. Ví dụ: Giả sử chúng ta lại có 512 MB. Chúng ta cần malloc32 mảng số nguyên. Đây là những số nguyên điển hình - 4 byte mỗi số. Chúng tôi biết kích thước của các mảng này sẽ không bao giờ vượt quá 1024 số nguyên. Không có phân bổ bộ nhớ nào khác xảy ra trong chương trình của chúng tôi. Chúng ta có đủ bộ nhớ không? 32 * 1024 * 4 = 131,072. 128 KB - vì vậy có. Chúng tôi có nhiều không gian. Nếu chúng ta biết rằng chúng ta sẽ không bao giờ cấp phát bất kỳ bộ nhớ nào nữa, chúng ta có thể an toànmalloccác mảng đó mà không giải phóng chúng. Tuy nhiên, điều này cũng có nghĩa là bạn phải khởi động lại máy / thiết bị nếu chương trình của bạn bị treo. Nếu bạn bắt đầu / dừng chương trình của mình 4.096 lần, bạn sẽ phân bổ tất cả 512 MB. Nếu bạn có các quy trình zombie, có thể bộ nhớ sẽ không bao giờ được giải phóng, ngay cả sau khi gặp sự cố.

Hãy cứu lấy nỗi đau và sự khốn khổ của bản thân, và sử dụng câu thần chú này như Một sự thật: mallocnên luôn được kết hợp với a free. newnên luôn luôn có a delete.


2
Trong hầu hết các hệ thống nhúng và thời gian thực, một quả bom hẹn giờ gây ra lỗi chỉ sau 73 giờ sẽ là một vấn đề nghiêm trọng.
Ben Voigt

số nguyên điển hình ??? Số nguyên ít nhất là số 16 bit và trên các vi mạch nhỏ thường là 16 bit. Nói chung, có nhiều thiết bị hơn có sizeof(int)bằng 2 thay vì 4.
ST3

2

Tôi nghĩ tuyên bố được nêu trong câu hỏi là vô nghĩa nếu theo nghĩa đen từ quan điểm của lập trình viên, nhưng nó có sự thật (ít nhất là một số) theo quan điểm của hệ điều hành.

malloc () cuối cùng sẽ gọi mmap () hoặc sbrk () để tìm nạp một trang từ HĐH.

Trong bất kỳ chương trình không tầm thường nào, khả năng trang này được trả lại cho HĐH trong suốt vòng đời của các tiến trình là rất nhỏ, ngay cả khi bạn giải phóng () hầu hết bộ nhớ được cấp phát. Vì vậy, bộ nhớ trống () 'd sẽ chỉ có sẵn cho cùng một tiến trình, nhưng không khả dụng cho những người khác.


2

Các giáo sư của bạn không sai, nhưng cũng không sai (ít nhất họ cũng gây hiểu lầm hoặc đơn giản hóa quá mức). Phân mảnh bộ nhớ gây ra các vấn đề về hiệu suất và sử dụng hiệu quả bộ nhớ, vì vậy đôi khi bạn phải cân nhắc và thực hiện hành động để tránh nó. Một thủ thuật cổ điển là, nếu bạn phân bổ nhiều thứ có cùng kích thước, hãy lấy một vùng bộ nhớ khi khởi động là một số bội số của kích thước đó và quản lý việc sử dụng nó hoàn toàn bên trong, do đó đảm bảo bạn không có sự phân mảnh xảy ra khi Mức hệ điều hành (và các lỗ trong trình ánh xạ bộ nhớ trong của bạn sẽ có kích thước chính xác phù hợp với đối tượng tiếp theo của loại đó đi kèm).

Có toàn bộ thư viện của bên thứ ba không làm gì khác ngoài xử lý loại việc đó cho bạn và đôi khi đó là sự khác biệt giữa hiệu suất chấp nhận được và thứ gì đó chạy quá chậm. malloc()free() mất một khoảng thời gian đáng kể để thực thi, điều này bạn sẽ bắt đầu nhận thấy nếu bạn đang gọi chúng nhiều.

Vì vậy, bằng cách tránh chỉ sử dụng một cách ngây thơ malloc()free()bạn có thể tránh được cả vấn đề phân mảnh và hiệu suất - nhưng khi bạn bắt tay vào nó, bạn phải luôn đảm bảo free()mọi thứ của mình malloc()trừ khi bạn có lý do chính đáng để làm khác. Ngay cả khi sử dụng nhóm bộ nhớ trong, một ứng dụng tốt sẽfree() bộ nhớ chung trước khi nó thoát. Có, hệ điều hành sẽ dọn dẹp nó, nhưng nếu vòng đời của ứng dụng được thay đổi sau đó, sẽ dễ dàng quên rằng nhóm vẫn tồn tại xung quanh ...

Các ứng dụng chạy lâu tất nhiên cần phải hết sức cẩn thận trong việc dọn dẹp hoặc tái chế mọi thứ chúng đã cấp phát, nếu không chúng sẽ hết bộ nhớ.


1

Các giáo sư của bạn đang nêu ra một điểm quan trọng. Thật không may, cách sử dụng tiếng Anh là như vậy mà tôi không hoàn toàn chắc chắn những gì họ nói. Hãy để tôi trả lời câu hỏi về các chương trình không phải đồ chơi có các đặc điểm sử dụng bộ nhớ nhất định và cá nhân tôi đã làm việc với.

Một số chương trình hoạt động tốt. Chúng phân bổ bộ nhớ theo từng đợt: rất nhiều phân bổ cỡ nhỏ hoặc trung bình, theo sau là rất nhiều giải phóng, trong các chu kỳ lặp lại. Trong các chương trình này, các trình cấp phát bộ nhớ điển hình hoạt động khá tốt. Chúng kết hợp các khối được giải phóng và khi kết thúc wave, phần lớn bộ nhớ trống nằm trong các khối lớn liền kề. Những chương trình này khá hiếm.

Hầu hết các chương trình hoạt động không tốt. Chúng phân bổ và phân bổ bộ nhớ ít nhiều một cách ngẫu nhiên, với nhiều kích cỡ khác nhau từ rất nhỏ đến rất lớn và chúng duy trì mức sử dụng cao các khối được cấp phát. Trong các chương trình này, khả năng kết hợp các khối bị hạn chế và theo thời gian, chúng kết thúc với bộ nhớ bị phân mảnh cao và tương đối không liền kề. Nếu tổng mức sử dụng bộ nhớ vượt quá khoảng 1,5GB trong không gian bộ nhớ 32-bit và có phân bổ (giả sử) 10MB trở lên, cuối cùng một trong những phân bổ lớn sẽ không thành công. Các chương trình này là phổ biến.

Các chương trình khác giải phóng ít hoặc không có bộ nhớ cho đến khi chúng dừng lại. Chúng dần dần phân bổ bộ nhớ trong khi chạy, chỉ giải phóng một lượng nhỏ, sau đó dừng lại, lúc đó tất cả bộ nhớ được giải phóng. Một trình biên dịch là như thế này. VM cũng vậy. Ví dụ, thời gian chạy .NET CLR, bản thân nó được viết bằng C ++, có thể không bao giờ giải phóng bất kỳ bộ nhớ nào. Tại sao nên làm thế?

Và đó là câu trả lời cuối cùng. Trong những trường hợp chương trình sử dụng bộ nhớ quá lớn, thì việc quản lý bộ nhớ bằng cách sử dụng malloc và miễn phí không phải là câu trả lời đầy đủ cho vấn đề. Trừ khi bạn đủ may mắn để xử lý một chương trình hoạt động tốt, bạn sẽ cần thiết kế một hoặc nhiều trình cấp phát bộ nhớ tùy chỉnh để phân bổ trước các phần lớn bộ nhớ và sau đó phân bổ phụ theo chiến lược bạn chọn. Bạn hoàn toàn không được sử dụng miễn phí, ngoại trừ khi chương trình dừng lại.

Nếu không biết chính xác những gì các giáo sư của bạn nói, đối với những chương trình có quy mô sản xuất thực sự, tôi có thể sẽ đứng về phía họ.

BIÊN TẬP

Tôi sẽ trả lời một số lời chỉ trích. Rõ ràng SO không phải là một nơi tốt cho những bài viết kiểu này. Chỉ cần nói rõ: Tôi đã có khoảng 30 năm kinh nghiệm viết loại phần mềm này, bao gồm một vài trình biên dịch. Tôi không có tài liệu tham khảo về học thuật, chỉ là vết bầm tím của chính tôi. Tôi không thể không cảm thấy những lời chỉ trích đến từ những người có kinh nghiệm hạn hẹp hơn và ngắn hơn.

Tôi sẽ nhắc lại thông điệp chính của mình: cân bằng giữa malloc và free không phải là giải pháp đủ để phân bổ bộ nhớ quy mô lớn trong các chương trình thực. Liên kết khối là điều bình thường và sẽ tốn thời gian, nhưng nó không đủ. Bạn cần các trình phân bổ bộ nhớ nghiêm túc, thông minh, có xu hướng lấy bộ nhớ theo từng phần (sử dụng malloc hoặc bất cứ thứ gì) và hiếm khi miễn phí. Đây có lẽ là thông điệp mà các giáo sư của OP đã nghĩ đến, mà ông ấy đã hiểu nhầm.


1
Các chương trình hoạt động không tốt cho thấy rằng các nhà phân bổ tốt nên sử dụng các nhóm riêng biệt cho các phần có kích thước khác nhau. Với bộ nhớ ảo, việc có nhiều vùng khác nhau cách xa nhau không phải là vấn đề lớn. Nếu mỗi phần được làm tròn thành lũy thừa của hai, và mỗi nhóm chứa các phần tròn như vậy chỉ có một kích thước, tôi không thể thấy sự phân mảnh có thể trở nên tồi tệ như thế nào. Tệ nhất là một chương trình có thể đột nhiên ngừng quan tâm đến một phạm vi kích thước nhất định, để lại một số vùng trống phần lớn vẫn không được sử dụng; Tôi không nghĩ đây là hành vi rất phổ biến.
Marc van Leeuwen

5
Rất cần trích dẫn cho tuyên bố rằng các chương trình được viết thành thạo không giải phóng bộ nhớ cho đến khi ứng dụng đóng.

12
Toàn bộ câu trả lời này giống như một loạt các phỏng đoán và giả định ngẫu nhiên. Có gì để sao lưu bất kỳ điều này không?
Chris Hayes

4
Tôi không chắc ý của bạn khi nói rằng thời gian chạy .NET CLR không giải phóng bất kỳ bộ nhớ nào. Theo như tôi đã thử nghiệm, nếu nó có thể.
Theodoros Chatzigiannakis

1
@vonbrand: GCC có nhiều trình phân bổ, bao gồm cả thương hiệu thu gom rác của riêng mình. Nó tiêu thụ bộ nhớ trong khi vượt qua và thu thập nó giữa các lần vượt qua. Hầu hết các trình biên dịch cho các ngôn ngữ khác có nhiều nhất 2 lần chuyển và miễn phí ít hoặc không có bộ nhớ giữa các lần chuyển. Nếu bạn không đồng ý, tôi rất vui khi nghiên cứu bất kỳ ví dụ nào bạn đưa ra.
david.pfx

1

Tôi ngạc nhiên là chưa có ai trích dẫn Cuốn sách :

Cuối cùng thì điều này có thể không đúng, bởi vì bộ nhớ có thể đủ lớn để không thể sử dụng hết bộ nhớ trống trong thời gian tồn tại của máy tính. Ví dụ, có khoảng 3 ⋅ 10 13 micro giây trong một năm, vì vậy nếu chúng ta mắc lỗi một lần trên micro giây, chúng ta sẽ cần khoảng 10 15 ô bộ nhớ để tạo ra một cỗ máy có thể hoạt động trong 30 năm mà không hết bộ nhớ. Bộ nhớ nhiều như vậy có vẻ lớn một cách phi lý theo tiêu chuẩn ngày nay, nhưng nó không phải là không thể. Mặt khác, các bộ xử lý ngày càng nhanh hơn và một máy tính trong tương lai có thể có số lượng lớn các bộ xử lý hoạt động song song trên một bộ nhớ, do đó có thể sử dụng hết bộ nhớ nhanh hơn nhiều so với những gì chúng ta đã nghĩ.

http://sarabander.github.io/sicp/html/5_002e3.xhtml#FOOT298

Vì vậy, thực sự, nhiều chương trình có thể hoạt động tốt mà không cần bận tâm đến việc giải phóng bất kỳ bộ nhớ nào.


1

Tôi biết về một trường hợp khi giải phóng bộ nhớ rõ ràng còn tệ hơn là vô ích . Đó là, khi bạn cần tất cả dữ liệu của mình cho đến cuối thời gian tồn tại của quy trình. Nói cách khác, khi giải phóng chúng chỉ có thể thực hiện ngay trước khi chương trình kết thúc. Vì bất kỳ hệ điều hành hiện đại nào cũng quan tâm đến việc giải phóng bộ nhớ khi chương trình chết, nên việc gọi free()là không cần thiết trong trường hợp đó. Trên thực tế, nó có thể làm chậm quá trình kết thúc chương trình, vì nó có thể cần truy cập một số trang trong bộ nhớ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.