Compartir a través de


Excepciones: liberar objetos en excepciones

En este artículo se explica la necesidad y el método de liberar objetos cuando se produce una excepción. Contenido de los temas:

Las excepciones producidas por el marco o por la aplicación interrumpen el flujo de programa normal. Por lo tanto, es muy importante realizar un seguimiento cercano de los objetos para que pueda eliminarlos correctamente en caso de que se produzca una excepción.

Hay dos métodos principales para hacerlo.

  • Controle las excepciones localmente mediante las try palabras clave y y catch , a continuación, destruya todos los objetos con una instrucción .

  • Destruya cualquier objeto del catch bloque antes de iniciar la excepción fuera del bloque para su posterior control.

Estos dos enfoques se ilustran a continuación como soluciones para el ejemplo problemático siguiente:

void SomeFunc()        // Problematic code
{
   CPerson* myPerson = new CPerson;

   // Do something that might throw an exception.
   myPerson->SomeFunc();

   // Now destroy the object before exiting.
   // If SomeFunc above throws an exception this code will
   // not be reached and myPerson will not be deleted.
   delete myPerson;
}

Como se ha escrito anteriormente, myPerson no se eliminará si se produce una excepción por SomeFunc. La ejecución salta directamente al siguiente controlador de excepciones externo, pasando la salida de la función normal y el código que elimina el objeto. El puntero al objeto sale del ámbito cuando la excepción deja la función y la memoria ocupada por el objeto nunca se recuperará siempre que se ejecute el programa. Se trata de una fuga de memoria; se detectaría mediante el diagnóstico de memoria.

Control de la excepción localmente

El paradigma try/catch proporciona un método de programación defensiva para evitar fugas de memoria y asegurarse de que los objetos se destruyen cuando se producen excepciones. Por ejemplo, el ejemplo mostrado anteriormente en este artículo podría reescribirse de la siguiente manera:

void SomeFunc()
{
   CPerson* myPerson = new CPerson;

   try
   {
      // Do something that might throw an exception.
      myPerson->SomeFunc();
   }
   catch (CException* e)
   {
      // Handle the exception locally
      e->Delete();
   }

   // Now destroy the object before exiting.
   delete myPerson;
}

En este nuevo ejemplo se configura un controlador de excepciones para detectar la excepción y controlarla localmente. A continuación, sale de la función normalmente y destruye el objeto . El aspecto importante de este ejemplo es que se establece un contexto para detectar la excepción con los bloques try/catch . Sin un marco de excepción local, la función nunca sabría que se había producido una excepción y no tendría la oportunidad de salir normalmente y destruir el objeto.

Iniciar excepciones después de destruir objetos

Otra manera de controlar las excepciones es pasarlas al siguiente contexto externo de control de excepciones. En el catch bloque, puede realizar alguna limpieza de los objetos asignados localmente y, a continuación, iniciar la excepción para su posterior procesamiento.

La función throwing puede o no tener que desasignar objetos de montón. Si la función siempre desasigna el objeto de montón antes de devolverlo en el caso normal, la función también debe desasignar el objeto de montón antes de iniciar la excepción. Por otro lado, si la función normalmente no desasigna el objeto antes de devolverlo en el caso normal, debe decidir entre mayúsculas y minúsculas si se debe desasignar el objeto del montón.

En el ejemplo siguiente se muestra cómo se pueden limpiar los objetos asignados localmente:

void SomeFunc()
{
   CPerson* myPerson = new CPerson;

   try
   {
      // Do something that might throw an exception.
      myPerson->SomeFunc();
   }
   catch (CException* e)
   {
      e->ReportError();
      // Destroy the object before passing exception on.
      delete myPerson;
      // Throw the exception to the next handler.
      throw;
   }

   // On normal exits, destroy the object.
   delete myPerson;
}

El mecanismo de excepción desasigna automáticamente los objetos de marco; también se llama al destructor del objeto frame.

Si llama a funciones que pueden producir excepciones, puede usar bloques try/catch para asegurarse de detectar las excepciones y tener la oportunidad de destruir los objetos que ha creado. En concreto, tenga en cuenta que muchas funciones de MFC pueden producir excepciones.

Para obtener más información, vea Excepciones: Detectar y eliminar excepciones.

Consulte también

Manejo de Excepciones