GC liên quan đến một nguồn tài nguyên dự đoán và dành riêng . VM có toàn quyền kiểm soát nó và có toàn quyền kiểm soát những trường hợp nào được tạo và khi nào. Các từ khóa ở đây là "dành riêng" và "tổng kiểm soát". Xử lý được phân bổ bởi HĐH và con trỏ là ... con trỏ tốt cho các tài nguyên được phân bổ bên ngoài không gian được quản lý. Do đó, các thẻ điều khiển và con trỏ không bị hạn chế sử dụng bên trong mã được quản lý. Chúng có thể được sử dụng - và thường là - bởi mã được quản lý và không được quản lý chạy trên cùng một quy trình.
Một "Trình thu thập tài nguyên" sẽ có thể xác minh xem một tay cầm / con trỏ có được sử dụng trong một không gian được quản lý hay không, nhưng theo định nghĩa thì nó không biết về những gì xảy ra bên ngoài không gian bộ nhớ (và, để làm cho mọi thứ tồi tệ hơn có thể được sử dụng qua ranh giới quá trình).
Một ví dụ thực tế là .NET CLR. Người ta có thể sử dụng C ++ có hương vị để viết mã hoạt động với cả không gian bộ nhớ được quản lý và không được quản lý; xử lý, con trỏ và tham chiếu có thể được chuyển qua giữa mã được quản lý và không được quản lý. Mã không được quản lý phải sử dụng các cấu trúc / loại đặc biệt để cho phép CLR tiếp tục theo dõi các tham chiếu được tạo cho các tài nguyên được quản lý của nó. Nhưng đó là điều tốt nhất nó có thể làm. Nó không thể làm tương tự với các thẻ điều khiển và con trỏ, và do đó, Bộ sưu tập tài nguyên đã nói sẽ không biết liệu có ổn không khi phát hành một tay cầm hoặc con trỏ cụ thể.
chỉnh sửa: Liên quan đến .NET CLR, tôi không có kinh nghiệm phát triển C ++ với nền tảng .NET. Có thể có các cơ chế đặc biệt tại chỗ cho phép CLR tiếp tục theo dõi các tham chiếu đến các thẻ điều khiển / con trỏ giữa mã được quản lý và không được quản lý. Nếu đó là trường hợp thì CLR có thể xử lý thời gian tồn tại của các tài nguyên đó và giải phóng chúng khi có tất cả các tham chiếu đến chúng (ít nhất là trong một số trường hợp có thể). Dù bằng cách nào, các thực tiễn tốt nhất chỉ ra rằng xử lý (đặc biệt là những người trỏ đến tệp) và con trỏ nên được phát hành ngay khi không cần thiết. Bộ sưu tập tài nguyên sẽ không tuân thủ điều đó, đó là một lý do khác để không có.
chỉnh sửa 2: Nói chung, CLR / JVM / VM nói chung để viết một số mã để giải phóng một tay cầm cụ thể nếu nó chỉ được sử dụng trong không gian được quản lý. Trong .NET sẽ là một cái gì đó như:
// This class offends many best practices, but it would do the job.
public class AutoReleaseFileHandle {
// keeps track of how many instances of this class is in memory
private static int _toBeReleased = 0;
// the threshold when a garbage collection should be forced
private const int MAX_FILES = 100;
public AutoReleaseFileHandle(FileStream fileStream) {
// Force garbage collection if max files are reached.
if (_toBeReleased >= MAX_FILES) {
GC.Collect();
}
// increment counter
Interlocked.Increment(ref _toBeReleased);
FileStream = fileStream;
}
public FileStream { get; private set; }
private void ReleaseFileStream(FileStream fs) {
// decrement counter
Interlocked.Decrement(ref _toBeReleased);
FileStream.Close();
FileStream.Dispose();
FileStream = null;
}
// Close and Dispose the Stream when this class is collected by the GC.
~AutoReleaseFileHandle() {
ReleaseFileStream(FileStream);
}
// because it's .NET this class should also implement IDisposable
// to allow the user to dispose the resources imperatively if s/he wants
// to.
private bool _disposed = false;
public void Dispose() {
if (_disposed) {
return;
}
_disposed = true;
// tells GC to not call the finalizer for this instance.
GC.SupressFinalizer(this);
ReleaseFileStream(FileStream);
}
}
// use it
// for it to work, fs.Dispose() should not be called directly,
var fs = File.Open("path/to/file");
var autoRelease = new AutoReleaseFileHandle(fs);