Megosztás a következőn keresztül:


releaseHandleFailed MDA

Feljegyzés

Ez a cikk a .NET-keretrendszer vonatkozik. Ez nem vonatkozik a .NET újabb implementációira, beleértve a .NET 6-os és újabb verzióit.

A releaseHandleFailed felügyelt hibakeresési segéd (MDA) aktiválva van, ha értesíti a fejlesztőket, ha egy ReleaseHandle osztály metódusa származik SafeHandle vagy CriticalHandle visszatér false.

Hibajelenségek

Erőforrás- vagy memóriavesztések. Ha az ReleaseHandle osztály metódusa származik SafeHandle vagy CriticalHandle sikertelen, akkor előfordulhat, hogy az osztály által beágyazott erőforrás nem lett felszabadítva vagy megtisztítva.

Ok

A felhasználóknak meg kell adniuk a ReleaseHandle módszer implementálását, ha olyan osztályokat hoznak létre, amelyek származnak SafeHandle vagy CriticalHandle; így a körülmények az adott erőforrásra vonatkoznak. A követelmények azonban a következők:

  • SafeHandle a típusok pedig CriticalHandle a létfontosságú folyamaterőforrások körül lévő burkolókat jelölik. A memóriavesztés idővel használhatatlanná tenné a folyamatot.

  • A ReleaseHandle metódus nem hajthatja végre a függvényt. Ha a folyamat beszerez egy ilyen erőforrást, ReleaseHandle az egyetlen módja annak felszabadításának. Ezért a hiba erőforrásszivárgást von maga után.

  • Minden olyan hiba, amely az erőforrás futtatása ReleaseHandlesorán következik be, az az erőforrás kiadását akadályozza, maga a ReleaseHandle metódus implementációjának hibája. A programozó feladata annak biztosítása, hogy a szerződés teljesüljön, még akkor is, ha ez a kód más által létrehozott kódot hív meg a funkciójának végrehajtásához.

Resolution (Osztás)

Az MDA-értesítést generáló adott SafeHandle (vagy CriticalHandle) típust használó kódot felül kell vizsgálni, és meg kell keresni azokat a helyeket, ahol a nyers leíró értékét kinyeri a rendszer, SafeHandle és máshová másolja. Ez a hibák szokásos oka az implementációkon belül SafeHandle vagy CriticalHandle implementációkban, mivel a nyers leíró értékének használatát a futtatókörnyezet már nem követi nyomon. Ha a nyers fogópont másolása később bezárul, egy későbbi ReleaseHandle hívás meghiúsulhat, mert a bezárást ugyanazon a leírón próbálják meg végrehajtani, amely most érvénytelen.

A helytelen kezelési duplikációk számos módon fordulhatnak elő:

  • Keresse meg a metódus hívásait DangerousGetHandle . Az ehhez a metódushoz intézett hívásoknak rendkívül ritkanak kell lenniük, és a talált hívásokat és metódusokat kell körülvenni DangerousAddRefDangerousRelease . Ezek az utóbbi módszerek határozzák meg azt a kódterületet, amelyben a nyers leíró értéke biztonságosan használható. Ezen a régión kívül, vagy ha a referenciaszám soha nem növekszik az első helyen, a leíró értékét bármikor érvénytelenítheti egy másik szálra Dispose irányuló vagy Close egy másik szálra irányuló hívás. Miután az összes használatot DangerousGetHandle nyomon követtük, kövesse a nyers fogópont elérési útját, hogy ne adja át egy olyan összetevőnek, amely végül meghívja CloseHandle , vagy egy másik alacsony szintű natív metódus, amely felszabadítja a fogópontot.

  • Győződjön meg arról, hogy az érvényes nyers leíróértékkel való inicializálásához SafeHandle használt kódé a leíró. Ha egy leíró körül alkotja SafeHandle a kódját anélkül, hogy false a ownsHandle paramétert az alapkonstruktorban állítanák be, akkor a valódi és a SafeHandle valódi leíró tulajdonosa is megpróbálhatja bezárni a leírót, ami hibát ReleaseHandle okozhat, ha a SafeHandle verseny megszakad.

  • Ha egy SafeHandle alkalmazástartomány között rendezve van, ellenőrizze, hogy a SafeHandle használt származtatás szerializálhatóként van-e megjelölve. Azokban a ritka esetekben, amikor egy osztály szerializálhatóvá SafeHandle vált, implementálnia kell az ISerializable interfészt, vagy a szerializálási és deszerializálási folyamat manuális vezérlésére az egyik másik technikát kell használnia. Erre azért van szükség, mert az alapértelmezett szerializálási művelet a zárt nyers fogópont értékének bitenkénti klónozása, ami azt eredményezi, hogy két SafeHandle példány ugyanazt a fogópontot használja. Egy bizonyos ponton mindkettő megpróbál ugyanahhoz a fogóponthoz csatlakozni ReleaseHandle . A második SafeHandle lépés sikertelen lesz. A szerializálás SafeHandle során a megfelelő művelet az, ha meghívja a DuplicateHandle függvényt vagy egy hasonló függvényt a natív leírótípushoz, hogy külön jogi leírópéldányt készítsen. Ha a fogópont típusa nem támogatja ezt, akkor a SafeHandle körbefuttatás nem tehető szerializálhatóvá.

  • Nyomon követhető, hogy a leírók hol vannak korán bezárva, ami a metódus meghívásakor meghiúsulhat, ha ReleaseHandle egy hibakereső töréspontot helyez a leíró kiadásához használt natív rutinra, például a CloseHandle függvényre. Ez lehet, hogy nem lehetséges a stressz forgatókönyvek vagy akár közepes méretű funkcionális tesztek miatt a nagy forgalom, az ilyen rutinok gyakran foglalkozik. Segíthet a natív kiadási metódust meghívó kód kialakításában a hívó identitásának, esetleg egy teljes veremkövetésnek, valamint a felszabadított leíró értékének rögzítéséhez. A leíró értéke összehasonlítható az MDA által jelentett értékkel.

  • Vegye figyelembe, hogy egyes natív leírótípusok, például a függvényen keresztül CloseHandle kibocsátható Összes Win32-leíró ugyanazzal a leírónévtérrel működnek. Az egyik fogóponttípus hibás kiadása problémákat okozhat egy másikkal. Egy Win32-eseményfogópont kétszeri véletlen bezárása például egy látszólag nem kapcsolódó fájlleíró idő előtti bezárásához vezethet. Ez akkor fordul elő, ha a leíró felszabadul, és a leíró értéke elérhetővé válik egy másik erőforrás nyomon követésére, esetleg egy másik típusú erőforrás nyomon követésére. Ha ez történik, és egy hibás második kiadás követi, a nem kapcsolódó szál leírója érvénytelenné válhat.

Effektus a futtatókörnyezetre

Ez az MDA nincs hatással a CLR-re.

Hozam

Egy üzenet, amely jelzi, hogy egy SafeHandle vagy egy CriticalHandle nem sikerült megfelelően feloldani a leírót. Példa:

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

Konfiguráció

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

Példa

Az alábbiakban egy példakód látható, amely aktiválhatja az MDA-t 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);
}

Lásd még