OK một số câu trả lời về malloc đã được đăng.
Phần thú vị hơn là cách thức hoạt động miễn phí (và theo hướng này, malloc cũng có thể được hiểu rõ hơn).
Trong nhiều triển khai malloc / miễn phí, miễn phí thường không trả lại bộ nhớ cho hệ điều hành (hoặc ít nhất là chỉ trong các trường hợp hiếm). Lý do là bạn sẽ có những khoảng trống trong heap của mình và do đó điều đó có thể xảy ra, rằng bạn chỉ cần kết thúc bộ nhớ ảo 2 hoặc 4 GB của mình bằng những khoảng trống. Điều này nên tránh, vì ngay khi bộ nhớ ảo kết thúc, bạn sẽ gặp rắc rối thực sự lớn. Lý do khác là, HĐH chỉ có thể xử lý các khối bộ nhớ có kích thước và căn chỉnh cụ thể. Cụ thể: Thông thường HĐH chỉ có thể xử lý các khối mà trình quản lý bộ nhớ ảo có thể xử lý (thường là bội số của 512 byte, ví dụ 4KB).
Vì vậy, trả lại 40 byte cho hệ điều hành sẽ không hoạt động. Vậy miễn phí làm gì?
Miễn phí sẽ đặt khối bộ nhớ trong danh sách khối miễn phí của riêng mình. Thông thường, nó cũng cố gắng kết hợp các khối liền kề với nhau trong không gian địa chỉ. Danh sách khối miễn phí chỉ là một danh sách vòng tròn của các khối bộ nhớ có một số dữ liệu quản trị ở đầu. Đây cũng là lý do tại sao việc quản lý các thành phần bộ nhớ rất nhỏ với malloc / free tiêu chuẩn không hiệu quả. Mỗi khối bộ nhớ cần dữ liệu bổ sung và với kích thước nhỏ hơn phân mảnh xảy ra nhiều hơn.
Danh sách miễn phí cũng là nơi đầu tiên mà malloc nhìn vào khi cần một đoạn bộ nhớ mới. Nó được quét trước khi nó gọi bộ nhớ mới từ HĐH. Khi một đoạn được tìm thấy lớn hơn bộ nhớ cần thiết, nó được chia thành hai phần. Một cái được trả lại cho người gọi, cái còn lại được đưa vào danh sách miễn phí.
Có nhiều tối ưu hóa khác nhau cho hành vi tiêu chuẩn này (ví dụ cho các đoạn bộ nhớ nhỏ). Nhưng vì malloc và miễn phí phải rất phổ biến, nên hành vi tiêu chuẩn luôn là dự phòng khi các lựa chọn thay thế không thể sử dụng được. Ngoài ra còn có tối ưu hóa trong việc xử lý danh sách miễn phí - ví dụ: lưu trữ các khối trong danh sách được sắp xếp theo kích thước. Nhưng tất cả các tối ưu hóa cũng có những hạn chế riêng của họ.
Tại sao mã của bạn bị sập:
Lý do là bằng cách viết 9 ký tự (đừng quên byte null theo dõi) vào một vùng có kích thước cho 4 ký tự, bạn có thể sẽ ghi đè lên dữ liệu quản trị được lưu trữ cho một đoạn bộ nhớ khác nằm trong "phía sau" khối dữ liệu của bạn ( vì dữ liệu này thường được lưu trữ "phía trước" các khối bộ nhớ). Khi rảnh thì cố gắng đưa đoạn của bạn vào danh sách miễn phí, nó có thể chạm vào dữ liệu quản trị này và do đó vấp phải một con trỏ bị ghi đè. Điều này sẽ sụp đổ hệ thống.
Đây là một hành vi khá duyên dáng. Tôi cũng đã thấy các tình huống trong đó một con trỏ chạy trốn ở đâu đó đã ghi đè lên dữ liệu trong danh sách không có bộ nhớ và hệ thống không gặp sự cố ngay lập tức nhưng một số chương trình con sau đó. Ngay cả trong một hệ thống phức tạp trung bình, các vấn đề như vậy có thể thực sự, rất khó để gỡ lỗi! Trong một trường hợp tôi đã tham gia, chúng tôi (một nhóm các nhà phát triển lớn hơn) phải mất vài ngày để tìm ra lý do của sự cố - vì nó nằm ở một vị trí hoàn toàn khác với vị trí được chỉ ra bởi kết xuất bộ nhớ. Nó giống như một quả bom hẹn giờ. Bạn biết đấy, "miễn phí" hoặc "malloc" tiếp theo của bạn sẽ gặp sự cố, nhưng bạn không biết tại sao!
Đó là một số vấn đề tồi tệ nhất của C / C ++ và một lý do tại sao con trỏ có thể gây ra vấn đề như vậy.