C++: Capturar excepciones del sistema operativo

Juguemos un rato con el siguiente código fuente:

 

   1: #include "stdafx.h"
   2: #include <Windows.h> 
   3:  
   4: int _tmain(int argc, _TCHAR* argv[])
   5: {
   6:     HANDLE hHeap=HeapCreate(HEAP_GENERATE_EXCEPTIONS,0,4096); 
   7:  
   8:     try
   9:     {
  10:         for(;;)
  11:             HeapAlloc(hHeap,HEAP_GENERATE_EXCEPTIONS,1024);
  12:     }
  13:     catch(...)
  14:     {
  15:         ;
  16:     } 
  17:  
  18:     HeapDestroy(hHeap);
  19:     return 0;
  20: } 

El programa es muy sencillo: crea un montículo local de 4Kb (una página de RAM) y luego se vuelve loco asignando bloques de 1KB. Como buenos programadores de C++ que somos, encerramos la asignación de memoria dentro de un bloque try y capturamos cualquier excepción que se pueda producir. Luego liberamos de un plumazo el montículo asignado, sin preocuparnos de los bloques que hemos asignado (que es una de las ventajas de trabajar con montículos locales).

Evidentemente, cuando intentemos asignar un bloque que no quepa, la función lanzará una excepción, que será capturada por nuestro bloque catch, ¿no? (Dejaremos como ejercicio para el lector el hecho de que la excepción ocurra en la tercera iteración y no en la quinta).

Pues si no hemos tocado nada de las opciones del proyecto, no. Nos saltará el IDE con una excepción no controlada en lugar de nuestro bloque de captura… mmmmm… curioso.

¿Qué está ocurriendo? Básicamente que el modelo de excepciones de Windows no es el mismo que el de C++; es decir, las excepciones producidas o lanzadas dentro de las funciones Win32 no son directamente compatibles con C++, quizás porque cuando Windows se hizo… el C++ era un animal mitológico que solamente unos pocos gurús utilizaban y que en general consistía en un metacompilador que generaba código C, sin estandarización alguna. También pudo haberse debido a que como Win32 se programa directamente en C, no se esperaba que el C++ tuviera la importancia que ahora tiene.

Pero entonces, ¿cómo capturo una excepción Win32? En el C de Microsoft (y por extensión también en su C++, ignoro si otros compiladores también lo soportan), existen los bloques __try/__except/__finally, que realizan una especie de pseudocontrol de excepciones un tanto barroco, ya que los parámetros para el bloque __exceptse definen de una forma un tanto estrambótica.

Como este tipo de control de excepciones no se debe puede mezclar con el de C++, no vamos a entrar en detalles sobre su funcionamiento, sino que vamos a poner un enlace con un ejemplo: http://msdn2.microsoft.com/en-us/library/ms681409(VS.85).aspx. Y este otro con el punto de entrad en la MSDN sobre el tema: http://msdn2.microsoft.com/en-us/library/ms680657(VS.85).aspx.

Entonces, ¿qué? ¿Se puede o no se puede? Pues claro que se puede, tan sólo hay que cambiar una opción del proyecto.

image

Nos vamos a la pantalla de que estamos viendo en la captura de arriba, y cambiamos en Enable C++ Exceptions” la opción por defecto de “Yes (EHsc)” por la mostrada en la imagen.

¿Qué hemos hecho? Pues le hemos dicho al compilador que habilite la compatibilidad con las excepciones de Win32, de forma que, una vez compilado el ejemplo de arriba con esta opción activada, se nos disparará correctamente la excepción.

Según la documentación, se pierde algo de optimización agresiva en las excepciones, pero pienso que las ventajas superan a los inconvenientes, ya que hemos normalizado el control de las excepciones.

Visual C++ 2008 Feature Pack en la calle

¿Recordáis esta entrada mía: Visual C++ 2008 Feature Pack? Pues ya es oficial, ya está en la calle la versión definitiva, que amplía las características del Visual C++, añadiendo




  • Soporte para temas visuales en MFC.


  • Soporte para la Ribbon de Office 2007.


  • Soporte para los temas visuales del Visual Studio y de Office 2003 (De hecho, hay un tipo de proyecto que te genera una estructura idéntica al Visual Studio 2008).


  • Soporte para diferentes colores en los temas.


  • Soporte para la TR1 (no tocan el compilador, sino que amplían la STL para cubrir dichas cosas nuevas).

Aquí el anuncio oficial, aquí la descarga oficial.


La única pega es que sólo se instala en las versiones en Inglés del Visual Studio 2008 Standard o superior… La disponibilidad para otros idiomas estará en un futuro Service Pack 1 que todavía no tiene fecha de salida…