Vấn đề chủ yếu là một cổ vật lịch sử, không phải là không thể thực hiện.
Cách mà hầu hết các trình biên dịch C xây dựng mã là để trình biên dịch chỉ nhìn thấy từng tệp nguồn tại một thời điểm; nó không bao giờ nhìn thấy toàn bộ chương trình cùng một lúc. Khi một tệp nguồn gọi một hàm từ một tệp nguồn khác hoặc một thư viện, tất cả trình biên dịch nhìn thấy là tệp tiêu đề có kiểu trả về của hàm, không phải là mã thực tế của hàm. Điều này có nghĩa là khi có một hàm trả về một con trỏ, trình biên dịch không có cách nào để biết liệu bộ nhớ mà con trỏ đang trỏ có cần được giải phóng hay không. Thông tin để quyết định không được hiển thị cho trình biên dịch tại thời điểm đó. Một lập trình viên con người, mặt khác, có thể tự do tra cứu mã nguồn của hàm hoặc tài liệu để tìm hiểu những gì cần phải làm với con trỏ.
Nếu bạn nhìn vào các ngôn ngữ cấp thấp hiện đại hơn như C ++ 11 hoặc Rust, bạn sẽ thấy rằng họ chủ yếu giải quyết vấn đề bằng cách làm cho quyền sở hữu bộ nhớ rõ ràng trong loại con trỏ. Trong C ++, bạn sẽ sử dụng unique_ptr<T>
thay vì đơn giản T*
để giữ bộ nhớ và unique_ptr<T>
đảm bảo rằng bộ nhớ sẽ được giải phóng khi đối tượng đến cuối phạm vi, không giống như đồng bằng T*
. Lập trình viên có thể trao bộ nhớ từ cái này unique_ptr<T>
sang cái khác, nhưng chỉ có thể có một cái unique_ptr<T>
chỉ vào bộ nhớ. Vì vậy, luôn luôn rõ ràng ai sở hữu bộ nhớ và khi nào nó cần được giải phóng.
C ++, vì lý do tương thích ngược, vẫn cho phép quản lý bộ nhớ thủ công kiểu cũ và do đó tạo ra các lỗi hoặc cách để tránh sự bảo vệ của a unique_ptr<T>
. Rust thậm chí còn nghiêm ngặt hơn ở chỗ nó thực thi các quy tắc sở hữu bộ nhớ thông qua các lỗi biên dịch.
Đối với tính không ổn định, vấn đề tạm dừng và tương tự, vâng, nếu bạn tuân theo ngữ nghĩa C, không thể quyết định tất cả các chương trình khi bộ nhớ sẽ được giải phóng. Tuy nhiên, đối với hầu hết các chương trình thực tế, không phải bài tập học thuật hay phần mềm lỗi, hoàn toàn có thể quyết định khi nào miễn phí và khi nào không. Đó là lý do duy nhất tại sao con người có thể tìm ra khi nào nên giải phóng hay không ở nơi đầu tiên.