Compartir a través de


Errores y control de excepciones (Modern C++)

En C++ moderno, en la mayoría de los casos, la forma preferida para informar y controlar errores de tiempo de ejecución y errores lógicos es utilizar las excepciones.Esto es especialmente cierto cuando la pila puede contener varias llamadas de función entre la función que detecta el error y la función que tiene el contexto para saber cómo tratarlo.Las excepciones proporcionan una manera formal y bien definida para el código que detecta los errores de pasar la información de la pila de llamadas.

Errores de programa generalmente se dividen en dos categorías: errores de lógica que son causados por programación errores, por ejemplo, un error "índice fuera del intervalo" y errores en tiempo de ejecución que están fuera del control del programador, por ejemplo, un error de "servicio no disponible de la red".En la programación de estilo c y en COM, se administra el informe de errores devolviendo un valor que representa un código de error o un código de estado para una función determinada, o estableciendo una variable global que el llamador, opcionalmente, puede recuperar después de cada llamada de función para ver si se informaron de errores.Por ejemplo, programación de COM utiliza el valor devuelto HRESULT para comunicar errores al llamador y la API de Win32 tiene la función GetLastError para recuperar el último error que informó de la pila de llamadas.En ambos casos, es que el llamador para reconocer el código y responder adecuadamente.Si el llamador no controla explícitamente el código de error, el programa podría bloquearse sin advertencia o continuar ejecutar con datos erróneos y producir resultados incorrectos.

Las excepciones son las preferidas en C++ moderno por las razones siguientes:

  • Una excepción fuerza el código de llamada a reconocer una condición de error y controlarla.Las excepciones no controladas detienen la ejecución del programa.

  • Una excepción salta hasta el punto en la pila de llamadas que puede controlar el error.Funciones intermedias pueden dejar que la excepción a propagar.No es necesario coordinarse con otras capas.

  • El mecanismo de desenredo de pila de excepción destruye todos los objetos en el ámbito de acuerdo con reglas bien definidas después de que se produce una excepción.

  • Una excepción permite una clara separación entre el código que detecta el error y el código que controla el error.

El siguiente ejemplo simplificado muestra la sintaxis necesaria para iniciar y detectar excepciones de C++.

 
#include <stdexcept>
#include <limits>
#include <iostream>
 
using namespace std;
class MyClass
{
public:
   void MyFunc(char c)
   {
      if(c < numeric_limits<char>::max())
         throw invalid_argument("MyFunc argument too large.");
      //...
   }
};

int main()
{
   try
   {
      MyFunc(256); //oops!
   }
 
   catch(invalid_argument& e)
   {
      cerr << e.what() << endl;
      return -1;
   }
   //...
   return 0;
}

Las excepciones de C++ son similares a las de lenguajes, como C# y Java.En el try bloquear, si es una excepción produce será capturados en el primer asociado catch bloque cuyo tipo coincide con el de la excepción.En otras palabras, la ejecución salta desde el throw instrucción a la catch instrucción.Si se encuentra ningún bloque catch utilizable, std::terminate se invoca y cierra el programa.En C++, se puede producir cualquier tipo; Sin embargo, se recomienda que se produzca un tipo que se derive directa o indirectamente de std::exception.En el ejemplo anterior, el tipo de excepción, invalid_argument, se define en la biblioteca estándar de la <stdexcept> archivo de encabezado.C++ no proporciona y no requiere un finally bloque para asegurarse de que todos los recursos se liberan si se produce una excepción.La adquisición de recurso es la expresión de inicialización (RAII), que utiliza punteros inteligentes, proporciona la funcionalidad necesaria para la limpieza de recursos.Para obtener más información, vea Cómo: diseño para Exception Safety.Para obtener información acerca del mecanismo de desenredo de pila en C++, consulte Excepciones y pila Unwinding en C++.

Instrucciones básicas

Control de errores robusto es un desafío en cualquier lenguaje de programación.Aunque las excepciones proporcionan varias características compatibles con buen control de errores, no todo el trabajo por usted.Para obtener los beneficios del mecanismo de excepción, tenga en cuenta las excepciones al diseñar el código.

  • Utilice aserciones para comprobar los errores que no deben ocurrir nunca.Utilizar excepciones para comprobar los errores que pueden producirse, por ejemplo, errores de validación de entradas en los parámetros de las funciones públicas.Para obtener más información, vea Exceptions VS. Assertions.

  • Utilizar excepciones cuando el código que controla el error podría separarse desde el código que detecta el error con uno o más llamadas de función que se interpongan.Tenga en cuenta si desea utilizar códigos de error en su lugar en los bucles de rendimiento críticos al código que controla el error está estrechamente vinculados al código que lo detecta.Para obtener más información acerca de cuándo no utilizar las excepciones, consulte When Not to Use Exceptions.

  • Para cada función que puede producir o propagar una excepción, proporcionan una de las garantías de tres excepciones: la garantía de segura, la garantía básica o la garantía de nothrow (noexcept).Para obtener más información, vea Cómo: diseño para Exception Safety.

  • Iniciar excepciones por valor, catch por referencia.No se atrapan no puede controlar.Para obtener más información, vea Instrucciones para Throwing y Catching Excepciones (C++).

  • No utilice las especificaciones de excepción, que no se admiten en C ++ 11.Para obtener más información, vea Exception specifications and noexcept.

  • Utilizar tipos de excepción de la biblioteca estándar cuando se aplican.Derivar tipos de excepción personalizada desde el clase de excepción jerarquía.Para obtener más información, vea Cómo: Utilice objetos de excepción estándar de biblioteca.

  • No permitir excepciones escapar de los destructores o funciones de desasignación de memoria.

Las excepciones y rendimiento

El mecanismo de excepción tiene un rendimiento muy mínimo costo si se produce ninguna excepción.Si se produce una excepción, el coste del recorrido de pila y desenredo están comparable al costo de una llamada de función.Las estructuras de datos adicionales son necesarias para realizar un seguimiento de la pila de llamadas después de un try se entra en bloque y instrucciones adicionales son necesarios para desenredar la pila si se produce una excepción.Sin embargo, en la mayoría de los casos, el costo en rendimiento y consumo de memoria no es significativo.El efecto adverso de excepciones en el rendimiento es probable que sea significativo sólo en sistemas muy limitada de memoria o en rendimiento crítico loops donde es probable que se producen con regularidad un error y el código para controlar está asociado estrechamente con el código que informa de él.En cualquier caso, es imposible conocer el costo real de las excepciones sin generación de perfiles y la medición.Incluso en esos casos raros cuando el costo es importante, puede tararlo contra la mayor exactitud, facilidad de mantenimiento más fácil y otras ventajas proporcionadas por una política de excepción bien diseñada.

Excepciones VS. aserciones

Las excepciones y las aserciones son dos mecanismos diferentes para detectar errores en tiempo de ejecución en un programa.Utilice aserciones para probar condiciones durante el desarrollo que nunca debe ser true si todo el código es correcto.No hay ningún punto en el manejo de este tipo de error con una excepción, ya que el error indica que algo en el código tiene que ser fijo y no hace referencia a una condición de que el programa tiene que recuperarse en tiempo de ejecución.Una aserción detiene la ejecución de la instrucción para que se puede inspeccionar el estado del programa en el depurador; una excepción sigue en ejecución desde el primer controlador catch correspondiente.Utilizar excepciones para comprobar las condiciones de error que pueden producirse en tiempo de ejecución incluso si el código es correcto, por ejemplo, "archivo no encontrado" o "memoria insuficiente." Es posible que desee para recuperarse de estas condiciones, incluso si la recuperación sólo enviará un mensaje a un registro y termina el programa.Compruebe siempre argumentos a funciones públicas mediante el uso de excepciones.Incluso si su función es libre de errores, puede que no tenga control total sobre los argumentos que un usuario puede pasar a él.

Excepciones de C++ en lugar de las excepciones de SEH de Windows

Programas de c y C++ pueden utilizar el mecanismo de (SEH) en el sistema operativo Windows de control estructurado de excepciones.Los conceptos de SEH son similares a las excepciones de C++, salvo que utiliza SEH el __try, __except, y __finally construye en lugar de try y catch.En Visual C++, las excepciones de C++ se implementan para SEH.Sin embargo, cuando se escribe código de C++, utilice la sintaxis de la excepción de C++.

Para obtener más información sobre SEH, vea Control de excepciones estructurado (C++).

Noexcept y las especificaciones de excepciones

Las especificaciones de excepciones se introdujeron en C++ como una forma de especificar las excepciones que podría iniciar una función.Sin embargo, las especificaciones de excepción resultó problemáticas en la práctica y no se admiten en el C ++ 11 borrador de estándar.Le recomendamos que no utilice las especificaciones de excepción excepto throw(), lo que indica que la excepción no permite que escapen excepciones.Si debe utilizar las especificaciones de excepción del tipo throw(tipo de), tenga en cuenta que Visual C++ se aparta el estándar de determinadas maneras.Para obtener más información, vea Especificaciones de excepciones.El noexcept especificador es nueva en C ++ 11 como la alternativa preferida para throw().

Vea también

Conceptos

Cómo: Interfaz Entre Exceptional y código No - Exceptional

Otros recursos

Bienvenido a C++ (C++ moderno)

Referencia del lenguaje C++

Referencia de la biblioteca estándar de C++