Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Dica
Use ponteiros inteligentes em vez de manuais AddRef/Release. A contagem de referências manual é a fonte nº 1 de bugs COM (objetos vazados, uso após liberação, liberação dupla). O código C++ moderno deve usar ponteiros inteligentes que lidam com a contagem de referências automaticamente:
#include <wrl/client.h> // Microsoft::WRL::ComPtr
// ComPtr automatically calls AddRef on copy and Release on destruction
Microsoft::WRL::ComPtr<IStream> stream;
HRESULT hr = CreateStreamOnHGlobal(nullptr, TRUE, &stream);
if (FAILED(hr)) return hr;
// Pass to another interface — use .Get() for raw pointer
// Note: operator& on ComPtr asserts if it already holds a value.
// Use .ReleaseAndGetAddressOf() if the ComPtr may be non-null.
Microsoft::WRL::ComPtr<IUnknown> unknown;
hr = stream.As(&unknown); // Safe QueryInterface — no manual Release needed
Alternativas:
-
winrt::com_ptr<T>— Ponteiro inteligente C++/WinRT (requer C++17, integra-se às projeções do WinRT) -
wil::com_ptr_nothrow<T>— bibliotecas de implementação Windows (alternativa sem exceção)
As regras manuais AddRef/Release descritas abaixo ainda são relevantes para entender como o COM funciona internamente e para implementar servidores COM, mas o código do cliente raramente deve chamar esses métodos diretamente.
Em sistemas de objetos tradicionais, o ciclo de vida dos objetos, ou seja, os problemas em torno da criação e exclusão de objetos, é tratado implicitamente pela linguagem (ou pelo tempo de execução da linguagem) ou explicitamente pelos programadores de aplicativos.
Em um sistema em evolução, construído de forma descentralizada e composto por componentes reutilizados, já não se pode afirmar que qualquer cliente, ou mesmo qualquer programador, sempre "saiba" como lidar com o ciclo de vida de um componente. Para um cliente com os privilégios de segurança certos, ainda é relativamente fácil criar objetos por meio de uma solicitação simples, mas a exclusão de objeto é outra questão inteiramente. Não está necessariamente claro quando um objeto não é mais necessário e deve ser excluído. (Leitores familiarizados com ambientes de programação com coleta de lixo, como Java, podem discordar; no entanto, objetos Java não ultrapassam os limites da máquina nem mesmo do processo e, portanto, a coleta de lixo fica restrita aos objetos que existem dentro do espaço de um único processo. Além disso, Java impõe o uso de uma única linguagem de programação.) Mesmo quando o cliente original termina de usar o objeto, ele não pode simplesmente desativá-lo, porque algum outro cliente ou outros clientes ainda podem ter uma referência a ele.
Uma maneira de garantir que um objeto não seja mais necessário é depender inteiramente de um canal de comunicação subjacente para informar o sistema quando todas as conexões com um objeto entre processos ou entre canais tiverem desaparecido. No entanto, esquemas que usam esse método são inaceitáveis por várias razões. Um problema é que ele pode exigir uma grande diferença entre o modelo de programação entre processos/redes e o modelo de programação de processo único. No modelo de programação entre processos/entre redes, o sistema de comunicação forneceria os ganchos necessários para o gerenciamento de tempo de vida do objeto, enquanto no modelo de programação de processo único, os objetos são conectados diretamente sem qualquer canal de comunicação intervindo. Outro problema é que esse esquema também pode resultar em uma camada de software fornecido pelo sistema que interferiria no desempenho do componente no caso em processo. Além disso, um mecanismo baseado no monitoramento explícito não tende a ser dimensionado em direção a milhares ou milhões de objetos.
O COM oferece uma abordagem escalonável e distribuída para esse conjunto de problemas. Os clientes informam a um objeto quando estão usando-o e quando terminarem, e os objetos se excluem quando não forem mais necessários. Essa abordagem exige que todos os objetos contabilizem referências para si mesmos. Linguagens de programação como Java, que por natureza têm seus próprios mecanismos de gerenciamento do ciclo de vida, como a coleta de lixo, podem usar a contagem de referências do COM para implementar e usar objetos COM internamente, permitindo que o programador evite lidar com isso.
Assim como um aplicativo deve liberar memória que alocou depois que a memória não estiver mais em uso, um cliente de um objeto será responsável por liberar suas referências ao objeto quando esse objeto não for mais necessário. Em um sistema orientado a objetos, o cliente pode fazer isso apenas dando ao objeto uma instrução para se libertar.
É importante que um objeto seja desalocado quando ele não estiver mais sendo usado. A dificuldade está em determinar quando é apropriado desalocar um objeto. Isso é fácil com variáveis automáticas (aquelas alocadas na pilha)— elas não podem ser usadas fora do bloco em que são declaradas, portanto, o compilador as desaloca quando o final do bloco é atingido. Para objetos COM, que são alocados dinamicamente, cabe aos clientes de um objeto decidir quando eles não precisam mais usar o objeto, especialmente objetos locais ou remotos que podem estar em uso por vários clientes ao mesmo tempo. O objeto deverá aguardar até todos os clientes terminarem de usá-lo antes de se liberar. Como os objetos COM são manipulados por meio de ponteiros de interface e podem ser usados por objetos em processos diferentes ou em outros computadores, o sistema não pode acompanhar os clientes de um objeto.
O método COM de determinar quando é apropriado desalocar um objeto é a contagem manual de referências. Cada objeto mantém uma contagem de referência que rastreia quantos clientes estão conectados a ele , ou seja, quantos ponteiros existem para qualquer uma de suas interfaces em qualquer cliente.
Para obter mais informações, consulte estes tópicos:
Tópicos relacionados: