Share via


releaseHandleFailed MDA

releaseHandleFailed Yönetilen hata ayıklama yardımcısı (MDA), veya CriticalHandle öğesinden SafeHandle 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.

Nedeni

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ındaki sarmalayıcıları temsil eder. 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ütmesi ReleaseHandlesırasında, kaynağın yayınlanmasını engelleyen herhangi bir hata, yöntemin ReleaseHandle uygulanması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 getirildiğinden emin olmak programcının sorumluluğundadır.

Çözüm

MDA bildirimini oluşturan belirli SafeHandle (veya CriticalHandle) türünü kullanan kod gözden geçirilerek 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 normal nedeni budur. Ham tanıtıcı kopyası daha sonra kapatılırsa, kapatma işlemi aynı tanıtıcıda denendiğinden sonraki ReleaseHandle bir çağrının başarısız olmasına neden olabilir ve bu da 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 veya başka bir iş parçacığında yapılan bir çağrıyla DisposeClose geçersiz kılınabilir. Tüm kullanımları DangerousGetHandle izlendikten sonra ham tanıtıcının izlediği yolu izleyerek 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 olmanız 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 olarak ayarlamadan ownsHandle kodunuzun sahip olmadığı bir tanıtıcının çevresinde bir SafeHandle oluşturursanız, hem hem de SafeHandle gerçek tanıtıcı sahibi tutamacı kapatmayı deneyebilir ve yarışı kaybederse hataya SafeHandleReleaseHandle neden olur.false

  • bir SafeHandle uygulama etki alanları arasında sıralandığında, kullanılan türetmenin SafeHandle seri hale getirilebilir olarak işaretlendiğini onaylayın. Bir sınıfından türetilen SafeHandle bir sınıfın serileştirilebilir hale getirildiği nadir durumlarda, arabirimi uygulamalı ISerializable veya serileştirme 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 olduklarını düşünmesine neden olur. Her ikisi de belirli bir noktada aynı tanıtıcıyı ç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, tür sarmalama işlemi seri 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ısı kesme noktası yerleştirerek, yöntemin son olarak çağrıldığında hataya ReleaseHandle neden olan tanıtıcının erken kapatıldığı yeri izlemek mümkün olabilir. Bu durum stres senaryoları ve hatta yoğun trafik nedeniyle 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 kodun işaretlenmesine 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 işleyicisini 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 durum, 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 durumda ve ardından hatalı bir ikinci sürüm geliyorsa, ilişkisiz 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 SafeHandle veya öğesinin tutamacı düzgün bir şekilde serbest bırakalamadığını belirten bir CriticalHandle ileti. Örnek:

"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.