with try son runtime_error que las instrucciones example error clase catch c++ exception stl

try - Regla de No-excepciones de la guía de estilo de Google C++; STL?



std::exception (7)

La guía de estilo C ++ de Google dice "No usamos excepciones". El estilo no menciona STL con respecto al uso de la excepción. Dado que las asignaciones de STL pueden fallar, ¿cómo manejan las excepciones lanzadas por los contenedores?

  1. Si usan STL, ¿cómo se informa a la persona que llama de las fallas de asignación? Los métodos STL como push_back() o map operator[] no devuelven ningún código de estado.
  2. Si no usan STL, ¿qué implementación de contenedor usan?

Dicen que no usan excepciones, no que nadie debería usarlas. Si miras el razonamiento, también escriben:

Debido a que la mayoría del código C ++ existente en Google no está preparado para tratar con excepciones, es relativamente difícil adoptar un nuevo código que genere excepciones.

El problema de herencia habitual. :-(


Estoy bastante seguro de que quieren decir que no usan excepciones en su código. Si revisa su script cpplint , comprueba que esté incluyendo los encabezados correctos para los contenedores STL (como vector, lista, etc.).


He encontrado que Google menciona esto explícitamente sobre STL y excepciones (el énfasis es mío):

Aunque no debe usar excepciones en su propio código, se usan ampliamente en ATL y algunos STL, incluido el que viene con Visual C ++. Al usar ATL, debe definir _ATL_NO_EXCEPTIONS para deshabilitar excepciones. Debe investigar si también puede deshabilitar excepciones en su STL, pero si no, está bien activar excepciones en el compilador. (Tenga en cuenta que esto es solo para compilar el STL. No debe escribir usted mismo el código de manejo de excepciones ) .

No me gustan esas decisiones (suerte de que no estoy trabajando para Google), pero son bastante claras acerca de su comportamiento e intenciones.


No puede manejar las fallas de asignación de todos modos en los sistemas operativos modernos; como optimización del rendimiento, suelen sobrecomprimir la memoria. Por ejemplo, si llama a malloc() y solicita una gran cantidad de memoria en Linux, tendrá éxito incluso si la memoria requerida para respaldarla no está allí . Solo cuando accede, el núcleo realmente intenta asignar páginas para respaldarlo, y en ese punto es demasiado tarde para decirle que la asignación falló de todos modos.

Asi que:

  1. Excepto en casos especiales, no se preocupe por las fallas de asignación. Si la máquina se queda sin memoria, es una falla catastrófica de la cual no puede recuperarse de manera confiable.

  2. Sin embargo, es una buena práctica capturar excepciones no controladas y registrar el resultado de e.what() , luego volver a throw , ya que puede ser más informativo que un backtrace, y las implementaciones de bibliotecas de C ++ típicas no lo hacen automáticamente.

  3. Todo el gran hilo de arriba sobre cómo no puedes confiar en que se cuelgue cuando te quedas sin memoria es una completa y completa basura. Es posible que el estándar C (++) no lo garantice, pero en los sistemas modernos, el bloqueo es lo único en lo que puede confiar si se queda sin memoria . En particular, no puede confiar en obtener NULL o, de hecho, ninguna otra indicación de su asignador, hasta e incluir una excepción de C ++.

  4. Si se encuentra en un sistema integrado en el que se puede acceder a la página cero, le sugiero encarecidamente que corrija esa situación asignando una página inaccesible a esa ubicación. No se puede confiar en que los seres humanos verifiquen punteros NULL todas partes, pero puede solucionarlo mapeando una página una vez en lugar de tratar de corregir todas las ubicaciones posibles (pasadas, presentes y futuras) en las que alguien haya omitido un NULL .

Calificaré lo anterior diciendo que es posible que esté utilizando algún tipo de asignador personalizado, o que esté en un sistema que no se compromete en exceso (los sistemas integrados sin intercambio son un ejemplo de eso, pero no el único ejemplo). En ese caso, tal vez pueda manejar con elegancia las condiciones de falta de memoria en su sistema . Pero, en general, en el siglo XXI, me temo que es poco probable que tengas la oportunidad; Lo primero que sabrá es que su sistema se queda sin memoria cuando las cosas empiezan a fallar.


Simplemente no manejamos las excepciones lanzadas por los contenedores, al menos en el código de nivel de aplicación.

He sido ingeniero en la Búsqueda de Google trabajando en C ++ desde 2008. Usamos contenedores STL a menudo. Personalmente, no puedo recordar un solo fallo o error importante que alguna vez se remontara a algo como vector :: push_back () o map :: operator [] que falla, donde dijimos "oh amigo, tenemos que reescribir este código porque la asignación podría fallar "o" dang, si solo usamos excepciones, esto podría haberse evitado ". ¿Alguna vez un proceso se queda sin memoria? Sí, pero esto suele ser un error simple (por ejemplo, alguien agregó un nuevo archivo de datos grande al programa y olvidó aumentar la asignación de RAM) o una falla catastrófica donde no hay una buena manera de recuperar y continuar. Nuestro sistema ya administra y reinicia los trabajos automáticamente para ser robustos para las máquinas con discos defectuosos, rayos cósmicos, etc., y esto no es realmente diferente.

Por lo que puedo decir, no hay ningún problema aquí.


Solo hay una posibilidad de manejar la falla de asignación bajo los supuestos resumidos en la pregunta:

  • esa aplicación de fuerza de asignador sale de la falla de asignación. En particular, esto requiere el asignador de cusror.

Las excepciones de índice de límite son menos interesantes en este contexto, porque la aplicación puede garantizar que no se realizarán mediante controles previos.


Stl solo está lanzando directamente en caso de fallo de asignación de memoria. Pero generalmente una aplicación del mundo real puede fallar por una variedad de razones, la falla de asignación de memoria es solo una de ellas. En los sistemas de 32 bits, la falla de asignación de memoria no es algo que deba ignorarse, ya que puede ocurrir. De modo que toda la discusión anterior acerca de que la falla en la asignación de memoria no va a suceder es algo sin sentido. Incluso asumiendo esto, uno tendría que escribir el código utilizando la inicialización en dos pasos. Y el manejo de excepciones C ++ es anterior a las arquitecturas de 64 bits por mucho tiempo. No estoy seguro de cuán lejos debo llegar para dignificar la profesionalidad negativa que se muestra aquí en google y solo responder la pregunta. Recuerdo un artículo de IBM de alrededor de 1997 que decía qué tan bien entendían y apreciaban las personas de IBM las implicaciones del manejo de excepciones C ++. Ok profesionalismo no es necesario un indicador de éxito. Así que renunciar al manejo de excepciones no es solo un problema si uno usa STL. Es un problema si uno usa C ++ como tal. Significa darse por vencido

  • error del constructor
  • poder usar objetos miembro y objetos de clase base como argumentos para cualquiera de los siguientes constructores de clase base / miembro (sin ninguna prueba). No es de extrañar que la gente utilizara la construcción en dos pasos antes de que existiera el manejo de excepción de C ++.
  • renunciar a los mensajes de error jerárquicos y ricos en un entorno que permite que los clientes o terceros proporcionen código y emitir errores, que el escritor original del código de llamada no hubiera podido prever al escribir el código de llamada y podría haber proporcionado espacio para en su rango de código de error de retorno.
  • evita tales ataques como devolver un puntero a un objeto de memoria estática a la falla de asignación de mensajes que hicieron los autores de FlexLm
  • poder usar un asignador de memoria que devuelve direcciones en un archivo disperso mapeado de memoria. En este caso, la falla de asignación ocurre cuando uno accede a la memoria en cuestión. (Ok actualmente esto solo funciona en Windows pero Apple forzó al equipo de gnu a proporcionar la funcionalidad necesaria en el compilador de G ++. Será necesaria más presión del desarrollador de Linux g ++ para proporcionar la funcionalidad también para ellos) (¡Uy! Esto incluso se aplica a STL)
  • poder dejar atrás este código de estilo C (ignorando los valores de retorno) y tener que usar un depurador con el ejecutable de depuración para descubrir qué falla en un entorno no trivial con procesos secundarios y bibliotecas compartidas proporcionadas por terceros o ejecuciones remotas
  • poder devolver la información rica del error a la persona que llama sin simplemente dejar todo en stderr