Reglas de recuento de referencia

Seleccione idioma Seleccione idioma
Id. de artículo: 104138 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

En el modelo de objetos componentes, duración de una interfaz se controla mediante recuento de referencias. El recuento de referencia para una interfaz, se manipula a través de las funciones miembro AddRef() y Release() heredadas de IUnknown. El miembro AddRef() incrementa el recuento de referencia de una interfaz y el método Release() disminuye lo. Una vez recuento de referencias la interfaz con un llega a cero, ya no hay cualquier punteros válidos para esa interfaz. Si el recuento de referencias en todas las interfaces de un objeto es cero, se puede liberar el objeto, porque ya no hay ningún punteros al objeto.

Más información

Reglas de recuento de referencia

En la lista siguiente es una copia de la referencia reglas (tomadas de las páginas 83 y 84 de la especificación de OLE 2.0) que deben ir seguidas de recuento. Ejemplos de código pequeño se han agregado en este artículo para ayudar a clarificar las reglas.

  1. Cada nueva copia de un puntero de interfaz debe ser AddRef d (), y cada destrucción de un puntero de interfaz debe ser Release () debería excepto donde las siguientes reglas permiten explícitamente lo contrario.

    1. parámetros de salida a funciones : el llamador debe AddRef() el parámetro real, porque será Release () ' d el destinatario cuando el out-value se almacena en la parte superior.
            LPOLEOBJECT lpObject;
               .
               .  // Get pointer to IOleObject.
               .
            LPVIEWOBJECT lpView = lpObject;
      
            lpObject->AddRef()
      
            // GetViewObject is a theoretical function that takes a
            // pointer to anything derived from IUnknown, and then
            // returns a pointer to IViewObject in the same variable
            // passed as the parameter. The AddRef() above is needed so
            // that the original pointer to IOleObject is not freed.
      
            GetViewObject(lpView);
      								
    2. obtención de una variable global : la copia local de un puntero de interfaz obtenido de una copia existente del puntero en una variable global debe ser independientemente referencia contada porque llama a funciones podría destruir la copia en el archivo global mientras la copia local está todavía activa.
            void function()
            {
            // Get a pointer to IOleObject from a global variable.
            LPOLEOBJECT lpOleObject = glpObject;
      
            // This AddRef() is needed so that the interface
            // pointed to by the global variable, glpObject,
            // does not get released by a different part of
            // the applications code.
      
            lpOleObject->AddRef();
               .
               . // use lpOleObject;
               .
            lpOleObject->Release();
            }
      								
    3. nuevos punteros sintetizados a partir de "aire" : una función que sintetiza un puntero de interfaz utilizando conocimientos interno especial en lugar de obtener de otro origen, debe realizar un AddRef() inicial en el puntero recién sintetizado. Importante estas rutinas de ejemplos de rutinas de creación de instancia, las implementaciones de IUnknown:: QueryInterface y así sucesivamente.
            STDMETHDOIMP IUnknown::QueryInteface( REFIID iidInterface,
                                               LPVOID FAR *ppvObj)
            {
            *ppvObj = NULL;
            SCODE sc = E_NOINTERFACE;
      
            if (iidInterface == IUnknown)
                {
                *ppvObj = this;
      
                // This AddRef() is needed because a new pointer
                // was just created.
      
                AddRef();
               sc = S_OK;
                }
      
            return ResultFromScode(sc);
            }
      								
    4. devuelve una copia de un puntero almacenado internamente : una vez haya obtenido el puntero, el destinatario no tiene idea cómo se relaciona su período de duración con que la copia almacenada internamente del puntero. Por lo tanto, el destinatario debe AddRef() el puntero copiar antes de volver a él.
            // m_lpOleObject is a private member variable of a C++ class.
            // GetOleObject is a member function to return access to this
            // pointer.
      
            void GetOleObject (LPVOID FAR *ppObject)
            {
                *ppObject = m_lpOleObject;
      
                // This AddRef() is needed due to this rule.
      
                m_lpOleObject->AddRef();
             }
      								
  2. Un conocimiento especial por parte de un fragmento de código acerca de las relaciones de comienzo y fin de la duración de dos o más copias de un puntero de interfaz puede permitir AddRef()/Release() pares que se omite.

    1. en el mismo parámetros para funciones : la copia de un puntero de interfaz que se pasa como parámetro real a una función tiene una duración está anidada en que el puntero utilizado para inicializar el valor. Por lo tanto, el parámetro real necesario no ser por separado referencia contada.
            void function (LPOLEOBJECT lpOleObject)
            {
      
            // Can use lpOleObject in this function
            // without doing AddRef() and Release().
      
            }
      								
    2. parámetros de salida de funciones, incluidos los valores devueltos : para establecer el parámetro de salida, la función por regla 1 debe tener una estable copia del puntero de interfaz. Al salir, se transfiere la responsabilidad de liberar el puntero desde el destinatario al llamador. Por lo tanto, el parámetro out no se necesita hacer referencia a contar.
            LPVIEWOBJECT lpView;
      
            HERROR hErr = lpOleObject->QueryInterface(IID_IViewObject,
                                                      (LPVOID FAR *)lpView);
      
            if (hErr = NOERROR)
                {
                // The QueryInterface succeeded. lpView does not have
                // to be AddRef()'d because it has already been done
                // by the QueryInterface method.
                }
      								
    3. las variables locales : una implementación de la función tiene claramente omniscient conocimiento de la duración de cada una de las variables de puntero asignadas en el marco de pila. Por lo tanto, puede utilizar este conocimiento para omitir pares AddRef()/Release() redundantes.
            void function()
            {
            LPOLEOBJECT lpTempObject;
               .
               .
               .
            lpTempObject = lpObject;
               .
               .  // lpTempObject can be used
               .  // without reference counting as long as
               .  // it is known that the lifetime of lpObject
               .  // outside of this function call.
               .
            }
      								
    4. Backpointers : algunas estructuras de datos son de la naturaleza del que contiene dos componentes, A y B, cada uno con un puntero a otro. Si la duración de un componente (A) se sabe que contiene la duración de la otra (B), el puntero desde el segundo componente para volver a la primera (de B a) necesita no referencia contarse. A menudo, evitar el ciclo que se crearía en caso contrario, es importante para mantener el comportamiento de liberar adecuado.

Propiedades

Id. de artículo: 104138 - Última revisión: miércoles, 03 de diciembre de 2003 - Versión: 3.1
La información de este artículo se refiere a:
  • Microsoft OLE 2.0
  • Microsoft OLE 4.0 sobre las siguientes plataformas
    • Microsoft Windows NT 4.0
    • Microsoft Windows NT 3.51 Service Pack 5
    • Microsoft Windows NT 4.0
    • Microsoft Windows 95
    • the operating system: Microsoft Windows 2000
Palabras clave: 
kbmt kbprogramming KB104138 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 104138

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com