Aracılığıyla paylaş


releaseHandleFailed MDA

Not

Bu makale .NET Framework'e özgüdür. .NET 6 ve sonraki sürümleri de dahil olmak üzere daha yeni .NET uygulamaları için geçerli değildir.

releaseHandleFailed Yönetilen hata ayıklama yardımcısı (MDA), veya öğesinden SafeHandleCriticalHandle türetilen bir sınıfın ReleaseHandle yöntemi döndürdüğünde falsegeliştiricileri bilgilendirmek için etkinleştirilir.

Belirtiler

Kaynak veya bellek sızıntıları. ReleaseHandle veya öğesinden SafeHandleCriticalHandle türetilen sınıfın yöntemi başarısız olursa, sınıf tarafından kapsüllenen kaynak serbest bırakılmamış veya temizlenmemiş olabilir.

Neden

Kullanıcılar veya CriticalHandle'den SafeHandle türetilen sınıflar oluştururlarsa yönteminin ReleaseHandle uygulanmasını sağlamalıdır; bu nedenle, koşullar tek tek kaynağa özgü olur. Ancak gereksinimler şunlardır:

  • SafeHandle ve CriticalHandle türleri, önemli işlem kaynakları etrafında sarmalayıcıları temsil eden. Bellek sızıntısı işlemi zaman içinde kullanılamaz hale getirir.

  • ReleaseHandle yöntemi işlevini gerçekleştirememelidir. İşlem böyle bir kaynağı aldıktan sonra serbest ReleaseHandle bırakmanın tek yoludur. Bu nedenle, hata kaynak sızıntıları anlamına gelir.

  • yürütülürken ReleaseHandlekaynağın yayımlanmasını engelleyen herhangi bir hata, yöntemin ReleaseHandle kendi uygulamasında bir hatadır. Kod, işlevini gerçekleştirmek için başka biri tarafından yazılan kodu çağırsa bile sözleşmenin yerine getirilmesini sağlamak programcının sorumluluğundadır.

Çözüm

MDA bildirimini yükselten belirli SafeHandle (veya CriticalHandle) türü kullanan kod gözden geçirilmelidir, ham tanıtıcı değerinin SafeHandle ayıklandığı ve başka bir yere kopyalandığı yerler aranmalıdır. Ham tanıtıcı değerinin kullanımı artık çalışma zamanı tarafından izlenmediğinden, veya CriticalHandle uygulamalarındaki SafeHandle hataların olağan nedeni budur. Ham tanıtıcı kopyası daha sonra kapatılırsa, kapatma aynı tanıtıcı üzerinde denendiğinden sonraki ReleaseHandle bir çağrının başarısız olmasına neden olabilir; bu artık geçersizdir.

Yanlış tanıtıcı yinelemesinin çeşitli yolları vardır:

  • yöntemine yapılan çağrıları DangerousGetHandle arayın. Bu yönteme yapılan çağrılar çok nadir olmalıdır ve bulduğunuz herhangi biri ve DangerousRelease yöntemlerine DangerousAddRef yapılan çağrılarla çevrelenmelidir. Bu ikinci yöntemler, ham tanıtıcı değerinin güvenli bir şekilde kullanılabileceğini kodun bölgesini belirtir. Bu bölgenin dışında veya başvuru sayısı hiçbir zaman ilk etapta artırılmadıysa, tanıtıcı değeri herhangi bir zamanda başka bir iş parçacığına yapılan veya Close başka bir iş parçacığına Dispose yapılan çağrıyla geçersiz kılınabilir. tüm kullanımları DangerousGetHandle izlendikten sonra, ham tanıtıcının sonunda çağıracak CloseHandle bir bileşene veya tanıtıcıyı serbest bırakacak başka bir alt düzey yerel yönteme teslim edilmediğinden emin olmak için izlediği yolu izlemeniz gerekir.

  • geçerli bir ham tanıtıcı değeriyle başlatmak SafeHandle için kullanılan kodun tanıtıcıya sahip olduğundan emin olun. Temel oluşturucuda parametresini ayarlamadan ownsHandle kodunuzun sahip olmadığı bir tanıtıcının etrafında bir SafeHandle tutamaç oluşturursanız, hem hem de SafeHandle gerçek tanıtıcı sahibi tutamacı kapatmayı deneyebilir ve yarışı kaybederse hataya SafeHandleReleaseHandle neden olabilir.false

  • Uygulama etki alanları arasında bir SafeHandle sıralandığında, kullanılan türetmenin SafeHandle serileştirilebilir olarak işaretlendiğini onaylayın. Türetilen SafeHandle bir sınıfın serileştirilebilir hale getirildiği nadir durumlarda, arabirimi uygulamalı ISerializable veya seri hale getirme ve seri durumdan çıkarma işlemini el ile denetlemek için diğer tekniklerden birini kullanmalıdır. Bu gereklidir çünkü varsayılan serileştirme eylemi, kapalı ham tanıtıcı değerinin bit düzeyinde bir kopyasını oluşturmaktır ve bu da iki SafeHandle örneğin aynı tanıtıcıya sahip olduğunu düşünmesine neden olur. Her ikisi de bir noktada aynı tanıtıcı üzerinde çağırmaya ReleaseHandle çalışır. Bunu yapmak için ikinci SafeHandle başarısız olur. bir seri hale getirildiğinde SafeHandle doğru eylem, benzersiz bir yasal tanıtıcı kopyası oluşturmak üzere yerel tanıtıcı türünüz için işlevi veya benzer bir işlevi çağırmaktır DuplicateHandle . Tanıtıcı türünüz bunu SafeHandle desteklemiyorsa, bunu sarmalama türü serileştirilebilir hale getirilemez.

  • Tanıtıcıyı serbest bırakmak için kullanılan yerel yordama (örneğin CloseHandle işlev) bir hata ayıklayıcı kesme noktası yerleştirerek, yöntemin sonunda çağrıldığında ReleaseHandle bir hataya neden olan tanıtıcının erken kapatıldığı yeri izlemek mümkün olabilir. Bu durum, yoğun trafik nedeniyle stres senaryoları ve hatta orta ölçekli işlevsel testler için mümkün olmayabilir. Çağıranın kimliğini veya büyük olasılıkla tam yığın izlemesini ve serbest bırakılan tanıtıcının değerini yakalamak için yerel yayın yöntemini çağıran kodu izlemeye yardımcı olabilir. Tanıtıcı değeri, bu MDA tarafından bildirilen değerle karşılaştırılabilir.

  • İşlev aracılığıyla yayınlanabilir tüm Win32 tanıtıcıları gibi bazı yerel tanıtıcı türlerinin aynı tanıtıcı ad alanını paylaştığını CloseHandle unutmayın. Bir tanıtıcı türünün hatalı bir şekilde serbest bırakılması, başka bir tanıtıcıyla ilgili sorunlara neden olabilir. Örneğin, bir Win32 olay tanıtıcısını yanlışlıkla iki kez kapatmak, ilgisiz görünen bir dosya tanıtıcısının erken kapatılmasına neden olabilir. Bu, tanıtıcı serbest bırakıldığında ve tanıtıcı değeri başka bir kaynağı izlemek için kullanılabilir hale geldiğinde (başka bir türde olabilir) gerçekleşir. Bu gerçekleşirse ve ardından hatalı bir ikinci sürüm gelirse, ilgisiz bir iş parçacığının tanıtıcısı geçersiz kılınabilir.

Çalışma Zamanı üzerindeki etkisi

Bu MDA'nın CLR üzerinde hiçbir etkisi yoktur.

Çıktı

bir veya öğesinin SafeHandle tanıtıcıyı düzgün bir şekilde serbest bırakalamadığını belirten bir CriticalHandle ileti. Örneğin:

"A SafeHandle or CriticalHandle of type 'MyBrokenSafeHandle'
failed to properly release the handle with value 0x0000BEEF. This
usually indicates that the handle was released incorrectly via
another means (such as extracting the handle using DangerousGetHandle
and closing it directly or building another SafeHandle around it."

Yapılandırma

<mdaConfig>
  <assistants>
    <releaseHandleFailed/>
  </assistants>
</mdaConfig>

Örnek

Aşağıda MDA'yi etkinleştirebilen bir kod örneği verilmiştir releaseHandleFailed .

bool ReleaseHandle()
{
    // Calling the Win32 CloseHandle function to release the
    // native handle wrapped by this SafeHandle. This method returns
    // false on failure, but should only fail if the input is invalid
    // (which should not happen here). The method specifically must not
    // fail simply because of lack of resources or other transient
    // failures beyond the user’s control. That would make it unacceptable
    // to call CloseHandle as part of the implementation of this method.
    return CloseHandle(handle);
}

Ayrıca bkz.