windows - tag - ¿Por qué mi fábrica COM nunca se lanza durante la vida útil del programa?
software tag music (1)
Tengo un servidor COM in-proc nativo de C ++ ATL. Un programa de prueba separado
- llama a
CoInitialize()
, - llama a
CoCreateInstance()
, luego - llama a
Release()
en el puntero, - luego llama a
CoUnitialize()
y sale.
Si ejecuto el programa de prueba en el depurador de Visual C ++, el depurador CRT informa una sola pérdida de memoria y cada vez que el número de asignación es el mismo.
Usé un enlace de asignación y descubrí que el objeto que no se devuelve al montón es el objeto de fábrica de clase.
Así que, básicamente, sucede lo siguiente:
- el programa llama a
CoCreateInstance()
- COM internamente llama a
DllGetClassObject()
- ATL crea una instancia de la fábrica y transfiere la propiedad a la persona que llama (elementos internos de COM)
y luego la fábrica nunca se lanza; no veo suficientes llamadas a Release()
de la fábrica de clases.
¿Que esta pasando? ¿Es eso un defecto en el tiempo de ejecución COM?
Resulta que es un problema de implementación de ATL.
El servidor usa una instancia de clase CComModule
global. Cuando se CComModule::DllClassObject()
crea una instancia de fábrica de clase y la almacena en caché en el mapa al que hace referencia el objeto CComModule
. De hecho, el objeto CComModule
posee la fábrica de clases. Cuando CComModule
destructor se ejecuta, no libera fábricas de clase en caché.
Para liberar todas las fábricas de clase almacenadas en caché, se debe llamar al método CComModule::Term()
antes de descargar el servidor. IMO, la forma más limpia de lograr esto, es derivar de CComModule
y llamar a CComModule::Term()
en el destructor de clase derivado.