GC , öngörülebilir ve ayrılmış bir kaynakla ilgilenir . Sanal Makine üzerinde tam denetime sahiptir ve hangi örneklerin ne zaman oluşturulacağı üzerinde tam denetime sahiptir. Buradaki anahtar kelimeler "ayrılmış" ve "toplam kontrol" dür. Kollar OS tarafından tahsis edilir ve işaretçiler ... yönetilen alanın dışında tahsis edilen kaynaklara iyi işaretçilerdir. Bu nedenle, tutamaçların ve işaretçilerin yönetilen kod içinde kullanılması kısıtlanmaz. Aynı işlemde çalışan yönetilen ve yönetilmeyen kodlar tarafından kullanılabilirler ve çoğu zaman kullanılabilirler.
Bir "Kaynak Toplayıcı" yönetilen bir alanda bir tanıtıcı / işaretçi kullanılıp kullanılmadığını doğrulayabilir, ancak tanım gereği bellek alanı dışında neler olup bittiğinden habersizdir (ve işleri daha da kötüleştirmek için bazı tutamaçlar kullanılabilir) süreç sınırları boyunca).
Pratik bir örnek .NET CLR'dir. Hem yönetilen hem de yönetilmeyen bellek alanlarıyla çalışan kod yazmak için aromalı C ++ kullanabilirsiniz; tanıtıcılar, işaretçiler ve referanslar yönetilen ve yönetilmeyen kodlar arasında aktarılabilir. Yönetilmeyen kod, CLR'nin yönetilen kaynaklara yapılan referansları izlemesini sağlamak için özel yapılar / türler kullanmalıdır. Ama yapabileceği en iyi şey bu. Kulplar ve işaretçiler için de aynı şeyi yapamaz ve bu nedenle Kaynak Toplayıcı belirli bir tutamacı veya işaretçiyi serbest bırakmanın uygun olup olmadığını bilemez.
edit: .NET CLR ile ilgili olarak, ben .NET platformu ile C ++ geliştirme ile deneyimli değilim. Belki CLR'nin yönetilen ve yönetilmeyen kodlar arasındaki tanıtıcılara / göstericilere yapılan referansları izlemeye devam etmesini sağlayan özel mekanizmalar vardır. Bu durumda, CLR bu kaynakların ömrünü halledebilir ve bunlara yapılan tüm referanslar silindiğinde bunları serbest bırakabilir (en azından bazı senaryolarda olabilir). Her iki durumda da, en iyi uygulamalar, tutamaçların (özellikle dosyalara işaret edenlerin) ve işaretçilerin gerekli olmadıkları anda serbest bırakılması gerektiğini belirtir. Bir Kaynak Toplayıcı buna uymayacaktır, bu bir kaynak olmamak için başka bir nedendir.
edit 2: Genel olarak CLR / JVM / VM'lerde, yalnızca yönetilen alan içinde kullanılıyorsa, belirli bir tanıtıcıyı serbest bırakmak için bazı kodlar yazmak nispeten önemsizdir. .NET'te şöyle bir şey olurdu:
// 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);