Pravidla správy paměti

Životnost ukazatelů na rozhraní je vždy spravována prostřednictvím metody AddRef a Release na každém rozhraní COM. Další informace naleznete v tématu Pravidla pro správu počtu odkazů.

Pro všechny ostatní parametry je důležité dodržovat určitá pravidla pro správu paměti. Následující pravidla platí pro všechny parametry metod rozhraní, včetně návratové hodnoty, které nejsou předány hodnotou:

  • Volající musí přidělit a uvolnit parametry v parametrech.
  • Parametry out-musí být přiděleny volanou; Uvolní je volající pomocí standardního alokátoru paměti úlohy MODELU COM. Další informace najdete v tématu Alokátor paměti OLE.
  • Parametry in/out-parameters jsou původně přiděleny volajícím a v případě potřeby uvolněny a relokovány volaným. Stejně jako u parametrů out je volající zodpovědný za uvolnění konečné vrácené hodnoty. Je nutné použít standardní alokátor paměti modelu COM.

V posledních dvou případech, kdy jeden kus kódu přidělí paměť a jinou část kódu uvolní, pomocí alokátoru COM zajistí, že dva části kódu používají stejné metody přidělování.

Další oblastí, která vyžaduje zvláštní pozornost, je ošetření out a in-out parametrů v podmínkách selhání. Pokud funkce vrátí kód selhání, volající obvykle nemá žádný způsob, jak vyčistit nebo vymazal parametry. To vede k následujícím dalším pravidlům:

  • V případě chybového stavu musí být parametry vždy spolehlivě nastaveny na hodnotu, která se vyčistí bez jakékoli akce volajícího.
  • Všechny parametry ukazatele musí být explicitně nastaveny na NULL. Obvykle se předávají v parametru ukazatele na ukazatel, ale mohou být předány také jako členy struktury, kterou volající přiděluje, a volané výplně kódu. Nejjednodušší způsob, jak zajistit, aby se tyto hodnoty (částečně) nastavily na null při zadávání funkce. Toto pravidlo je důležité, protože podporuje robustnější interoperabilitu aplikací.
  • Za chybových podmínek musí být všechny parametry in-out buď ponechány samostatně volaný kódem (tedy zůstávají na hodnotě, do které byly inicializovány volajícím) nebo musí být explicitně nastaveny, jako v případě vrácení chyby výstupního parametru.

Mějte na paměti, že tyto konvence správy paměti pro aplikace MODELU COM platí pouze pro veřejná rozhraní a rozhraní API; není nutné, aby přidělení paměti výhradně interní pro aplikaci MODELU COM bylo nutné provádět pomocí těchto mechanismů.

Warning

Běžné nástrahy v .NET / interoperabilitě spravovaného kódu: Při využívání rozhraní MODELU COM z .NET (C# nebo VB.NET) zpracovává modul runtime callable wrapper (RCW) většinu správy paměti automaticky. Pokud ale nevoláte funkci ve stylu MODELU COM, která vrací řetězec s přiděleným -přiděleným CoTaskMemAllocřetězcem (out LPWSTR), musíte ji uvolnit – Marshal.FreeCoTaskMem uvolňování paměti uvolňování paměti paměti úloh modelu COM nebude uvolněno:

// C# example — COM function returns a CoTaskMemAlloc'd string
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
static extern int SHGetKnownFolderPath(
    ref Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);

// Caller must free the returned string
IntPtr pathPtr = IntPtr.Zero;
try
{
    Guid folderId = new("374DE290-123F-4565-9164-39C4925E467B"); // Downloads
    int hr = SHGetKnownFolderPath(ref folderId, 0, IntPtr.Zero, out pathPtr);
    Marshal.ThrowExceptionForHR(hr);
    string path = Marshal.PtrToStringUni(pathPtr)!;
}
finally
{
    if (pathPtr != IntPtr.Zero)
        Marshal.FreeCoTaskMem(pathPtr); // Required — prevents memory leak
}

Empirické pravidlo: Pokud nativní funkce MODELU COM dokumentuje, že volající musí uvolnit out-parametr s CoTaskMemFree, spravovaný ekvivalent je Marshal.FreeCoTaskMem. Nikdy se nepoužívá Marshal.FreeHGlobal pro paměť úloh MODELU COM, protože se jedná o různé alokátory.

Com interně používá ke komunikaci mezi klienty a servery vzdálená volání procedur (RPC). Další informace o správě paměti v procedurách serveru RPC naleznete v tématu Správa paměti zástupné procedury serveru.