Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O tempo de vida dos ponteiros para interfaces é sempre gerenciado por meio dos métodos AddRef e Release em cada interface COM. Para obter mais informações, consulte regras para gerenciar contagens de referência.
Para todos os outros parâmetros, é importante aderir a certas regras para gerenciar a memória. As seguintes regras aplicam-se a todos os parâmetros dos métodos de interface — incluindo o valor de retorno — que não são passados por valor:
- Os parâmetros internos devem ser alocados e liberados pelo chamador.
- Os parâmetros externos devem ser alocados pelo chamado; eles são liberados pelo chamador usando o alocador de memória de tarefa COM padrão. Consulte o do alocador de memória OLE para obter mais informações.
- Os parâmetros de entrada/saída são inicialmente alocados pelo chamador e, em seguida, liberados e realocados pelo chamado, se necessário. Como é verdade para os parâmetros de saída, o chamador é responsável por liberar o valor final retornado. O alocador de memória COM padrão deve ser usado.
Nos dois últimos casos, em que um pedaço de código aloca a memória e um pedaço diferente de código a libera, o uso do alocador COM garante que as duas partes de código estejam usando os mesmos métodos de alocação.
Outra área que precisa de atenção especial é o tratamento de parâmetros de entrada e saída em condições de falha. Se uma função retorna um código de falha, o chamador normalmente não tem como limpar os parâmetros de entrada ou saída. Isto conduz às seguintes regras adicionais:
- No caso de uma condição de erro, os parâmetros devem sempre ser definidos de forma confiável para um valor que será limpo sem qualquer ação por parte do chamador.
- Todos os parâmetros de ponteiro de saída devem ser explicitamente definidos como NULL. Eles geralmente são passados em um parâmetro de ponteiro para ponteiro, mas também podem ser passados como membros de uma estrutura que o chamador aloca e o código chamado preenche. A maneira mais simples de garantir isso é (em parte) definir esses valores para NULL na entrada da função. Esta regra é importante porque promove uma interoperabilidade de aplicações mais robusta.
- Em condições de erro, todos os parâmetros de entrada e saída devem ser deixados sozinhos pelo código chamado (permanecendo assim no valor para o qual foram inicializados pelo chamador) ou ser explicitamente definidos, como no caso de retorno de erro do parâmetro de saída.
Lembre-se de que essas convenções de gerenciamento de memória para aplicativos COM se aplicam somente em interfaces públicas e APIs; não há nenhum requisito de que a alocação de memória estritamente interna a um aplicativo COM precise ser feita usando esses mecanismos.
Warning
Armadilha comum em .NET / interoperativa de código gerido: Ao consumir interfaces COM de .NET (C# ou VB.NET), o Runtime Callable Wrapper (RCW) gere automaticamente a maior parte da gestão de memória. No entanto, se P/Invokar uma função ao estilo COM que devolve uma CoTaskMemAllocstring -allocated (uma saída LPWSTR), deve libertá-la com Marshal.FreeCoTaskMem — o coletor de lixo não libertará memória de tarefa COM:
// 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
}
Regra geral: Se uma função COM nativa documentar que o chamador deve libertar um parâmetro de saída com CoTaskMemFree, o equivalente gerido é Marshal.FreeCoTaskMem. Nunca uses Marshal.FreeHGlobal para memória de tarefas COM, pois são alocadores diferentes.
A COM usa internamente chamadas de procedimento remoto (RPC) para se comunicar entre clientes e servidores. Para obter mais informações sobre como gerenciar memória em stubs de servidor RPC, consulte o tópico Server-stub Memory Management tópico.
Tópicos relacionados
- Gerenciando de alocação de memória