utilizar usar usan tag son sirve responder questions question que para las hacer ejemplos como c++ python c exception

c++ - usar - question tags ejemplos



¿Cómo se implementan las excepciones bajo el capó? (10)

Algunos tiempos de ejecución como el tiempo de ejecución de Objective-C tienen excepciones de costo cero de 64 bits. Lo que eso significa es que no cuesta nada ingresar a un bloque de prueba. Sin embargo, esto es bastante costoso cuando se lanza la excepción. Esto sigue el paradigma de "optimizar para el caso promedio": las excepciones están destinadas a ser excepcionales, por lo que es mejor presentar el caso cuando no hay excepciones realmente rápidas, incluso si se produce a costa de excepciones significativamente más lentas.

Casi todos los usan, pero muchos, incluido yo, simplemente damos por sentado que simplemente funcionan.

Estoy buscando material de alta calidad. Los idiomas que uso son: Java, C, C #, Python, C ++, por lo que estos son los que más me interesan.

Ahora, C ++ es probablemente un buen lugar para comenzar ya que puedes lanzar cualquier cosa en ese idioma.

Además, C está cerca del ensamblaje. ¿Cómo se podrían emular excepciones usando construcciones de C puro y sin ensamblaje?

Finalmente, escuché el rumor de que los empleados de Google no usan excepciones para algunos proyectos debido a consideraciones de velocidad. ¿Es solo un rumor? ¿Cómo se puede lograr nada sustancial sin ellos?

Gracias.


Aquí hay una forma común de implementar las excepciones de C ++:
http://www.codesourcery.com/public/cxx-abi/abi-eh.html

Es para la arquitectura Itanium, pero la implementación aquí descrita también se usa en otras arquitecturas. Tenga en cuenta que es un documento largo, ya que las excepciones de C ++ son complicadas.

Aquí hay una buena descripción de cómo LLVM implementa excepciones:
http://llvm.org/docs/ExceptionHandling.html

Como LLVM pretende ser una representación intermedia común para muchos tiempos de ejecución, los mecanismos descritos se pueden aplicar a muchos idiomas.


Con respecto al rendimiento, el uso escaso de excepciones probablemente tendrá efectos insignificantes, pero no los abuse.

Personalmente, he visto el código Java que tuvo dos órdenes de magnitud peor de lo que podría haber tenido (tomó aproximadamente x100 el tiempo) porque las excepciones se usaron en un ciclo importante en lugar de más if / returns estándar.


El código C ++ en Google (excepto algunos casos específicos de Windows) no usa excepciones: cfr google-styleguide.googlecode.com/svn/trunk/… , forma abreviada: "No usamos excepciones C ++". Citando de la discusión (presione la flecha para expandir la URL):

Nuestro consejo contra el uso de excepciones no se basa en fundamentos filosóficos o morales, sino en argumentos prácticos. Debido a que nos gustaría utilizar nuestros proyectos de código abierto en Google y es difícil hacerlo si esos proyectos usan excepciones, también debemos desaconsejar las excepciones en los proyectos de código abierto de Google. Las cosas probablemente serían diferentes si tuviéramos que hacerlo todo de nuevo desde cero.

Esta regla no se aplica al código de Google en otros idiomas, como Java y Python.


El mejor artículo que se ha escrito sobre la implementación de excepciones (bajo el capó) es Exception Handling en CLU, de Barbara Liskov y Alan Snyder. Me he referido a él cada vez que comencé un nuevo compilador.

Para una vista algo más alta de una implementación en C usando setjmp y longjmp , recomiendo las interfaces C y las implementaciones de Dave Hanson (como Eli Bendersky).


En su libro C Interfaces e implementaciones: Técnicas para crear software reutilizable , DR Hanson proporciona una implementación agradable de excepciones en C puro utilizando un conjunto de macros y setjmp/longjmp . Proporciona macros TRY / RAISE / EXCEPT / FINALLY que pueden emular casi todo lo que hacen las excepciones C ++ y más.

El código se puede leer here (mira except.h / except.c).

PD: tu pregunta sobre Google. De hecho, a sus empleados se les permite usar excepciones en el nuevo código, y la razón oficial de la prohibición en el código anterior es porque ya estaba escrito de esa manera y no tiene sentido mezclar estilos.

Personalmente, también creo que C ++ sin excepciones no es la mejor idea.


Las excepciones son solo un ejemplo específico de un caso más general de construcciones de control de flujo no locales avanzadas. Otros ejemplos son:

  • notificaciones (una generalización de excepciones, originalmente de algún viejo sistema de objetos Lisp, ahora implementado en, por ejemplo, CommonLisp e Ioke),
  • continuaciones (una forma más estructurada de GOTO , popular en idiomas de alto nivel y de orden superior),
  • corutinas (una generalización de subrutinas, popular especialmente en Lua),
  • generators à la Python (esencialmente una forma restringida de corutinas),
  • fibras (hilos cooperativos de peso ligero) y, por supuesto, los ya mencionados
  • GOTO .

(Estoy seguro de que hay muchos otros que extrañé).

Una propiedad interesante de estos constructos es que todos son aproximadamente equivalentes en poder expresivo: si tienes uno , puedes construir fácilmente todos los demás.

Entonces, la mejor manera de implementar excepciones depende de qué otras construcciones tenga disponibles:

  • Cada CPU tiene GOTO , por lo tanto, siempre puedes recurrir a eso, si es necesario.
  • C tiene setjmp / longjmp que son básicamente continuaciones de MacGyver (construidas con cinta adhesiva y mondadientes, que no son del todo reales, pero que al menos te sacarán del problema inmediato si no tienes algo mejor disponible).
  • La JVM y la CLI tienen sus propias excepciones, lo que significa que si la semántica de excepción de su idioma coincide con la de Java / C #, usted está en su casa libre (pero si no, entonces está jodido).
  • El Parrot VM como excepciones y continuaciones.
  • Windows tiene su propio marco para el manejo de excepciones, que los implementadores de lenguaje pueden usar para construir sus propias excepciones en la parte superior.

Un caso de uso muy interesante, tanto el uso de excepciones como la implementación de excepciones es el Proyecto Volta de Microsoft Live Lab. (Ahora difunto.) El objetivo de Volta era proporcionar una refacturación arquitectónica para aplicaciones web con solo presionar un botón. Por lo tanto, puede convertir su aplicación web de un nivel en una aplicación de dos o tres niveles simplemente colocando algunos atributos [Browser] o [DB] en su código .NET y el código se ejecutará automágicamente en el cliente o en el DB. Para hacer eso, el código .NET tuvo que traducirse al código fuente de JavaScript, obviamente.

Ahora, podría simplemente escribir una VM completa en JavaScript y ejecutar el bytecode sin modificaciones. (Básicamente, transfiera el CLR de C ++ a JavaScript). De hecho, hay proyectos que hacen esto (p. Ej., La VM HotRuby), pero esto es a la vez ineficiente y poco interoperable con otros códigos JavaScript.

Entonces, en cambio, escribieron un compilador que compila el bytecode CIL con el código fuente de JavaScript. Sin embargo, JavaScript carece de ciertas características que tiene .NET (generadores, subprocesos, también los dos modelos de excepción no son 100% compatibles) y, lo que es más importante, carece de ciertas características que los compiladores adoran (ya sea GOTO o continuaciones) y que podrían usarse para implementar las características que faltan mencionadas anteriormente.

Sin embargo, JavaScript tiene excepciones. Entonces, usaron JavaScript Exceptions para implementar Volta Continuations y luego utilizaron Volta Continuations para implementar excepciones .NET , generadores .NET e incluso .NET Managed Threads (!!!)

Por lo tanto, para responder a su pregunta original:

¿Cómo se implementan las excepciones bajo el capó?

Con excepciones, irónicamente! Al menos en este caso muy específico, de todos modos.

Otro gran ejemplo son algunas de las propuestas de excepción en la lista de correo de Go, que implementan excepciones usando Goroutines (algo así como una mezcla de corrutinas concurrentes y procesos de CSP). Otro ejemplo más es Haskell, que utiliza Monads, evaluación diferida, optimización de llamadas de cola y funciones de orden superior para implementar excepciones. Algunas CPU modernas también admiten bloques de construcción básicos para excepciones (por ejemplo, las CPU Vega-3 que fueron diseñadas específicamente para los aceleradores de cálculo Java de Azul Systems).


Lo más importante que debe manejar una implementación de excepción es cómo volver al manejador de excepciones una vez que se ha lanzado una excepción. Dado que puede haber realizado un número arbitrario de llamadas a funciones anidadas desde la instrucción try en C ++, debe desenrollar la búsqueda de la pila de llamadas para el controlador. Sin embargo, implementado, esto debe incurrir en el costo del tamaño del código de mantener suficiente información para realizar esta operación (y generalmente significa una tabla de datos para llamadas que pueden tomar excepciones). También significa que la ruta de ejecución del código dinámico será más larga que simplemente regresar de llamadas a funciones (que es una operación bastante económica en la mayoría de las plataformas). También puede haber otros costos dependiendo de la implementación.

El costo relativo variará según el idioma utilizado. El lenguaje de nivel superior utilizado, es menos probable que importe el costo del código, y la información puede conservarse independientemente de si se usan excepciones.

Una aplicación donde el uso de excepciones (y C ++ en general) a menudo se evita por buenas razones es el firmware incorporado. En las típicas plataformas bare metal o RTOS, puede tener 1MB de espacio de código, o 64K, o incluso más pequeño. Algunas plataformas son muy pequeñas, incluso C no es práctico de usar. En este tipo de entorno, el impacto del tamaño es relevante debido al costo mencionado anteriormente. También afecta la biblioteca estándar en sí misma. Los proveedores de herramientas incrustadas a menudo producirán una biblioteca sin excepción, lo que tiene un gran impacto en el tamaño del código. Los compiladores altamente optimizadores también pueden analizar el diagrama de llamadas y optimizar la información de marco de llamada necesaria para la operación de desenrollado para una considerable reducción de espacio. Las excepciones también dificultan el análisis de los requisitos en tiempo real.

En entornos más típicos, el costo del tamaño del código es casi seguro irrelevante y el factor de rendimiento es probablemente clave. Si los usa dependerá de sus requisitos de rendimiento y de cómo quiera usarlos. Usar excepciones en casos no excepcionales puede hacer un diseño elegante, pero a un costo de rendimiento que puede ser inaceptable para sistemas de alto rendimiento. Las implementaciones y el costo relativo variarán según la plataforma y el compilador, por lo que la mejor forma de comprender realmente si las excepciones son un problema es analizar el rendimiento de su propio código.


Los compiladores C / C ++ utilizan las funciones de sistema operativo subyacentes para el manejo de excepciones. Los marcos como .Net o Java también se basan, en la máquina virtual, en las instalaciones del sistema operativo. En Windows, por ejemplo, SEH, la infraestructura de gestión de excepciones estructuradas, realiza el trabajo pesado. Debe leer el antiguo artículo de referencia: Un curso acelerado sobre las profundidades del manejo estructurado de excepciones Win32 ™ .

En cuanto al costo de no usar excepciones, son caros pero ¿comparados con qué? Comparado con los códigos de error de retorno? Después de tener en cuenta el costo de la corrección y la calidad del código, las excepciones siempre ganarán para aplicaciones comerciales. A excepción de algunas funciones de nivel de sistema operativo muy críticas, las excepciones son siempre mejores en general.

Por último, pero no menos importante, está el anti-patrón de usar excepciones para el control de flujo. Las excepciones deben ser excepcionales y el código que abusa de las excepciones del control de flujo pagará el precio en rendimiento.


setjmp() y longjmp() generalmente.

La captura de excepciones tiene un costo no trivial, pero para la mayoría de los propósitos no es gran cosa.