Archive

Archive for the ‘Visual Studio’ Category

Mirada al Visual C++ 2010


En estos días Jonathan Wood creó un video en el que hace un sumario rápido sobre las nuevas características de Visual C++ 2010. El vídeo aquí.

El vídeo resulta interesante, desde luego. En éste, Wood afirma que Microsoft ha decidido retomar el camino del código nativo y su plataforma Win32 – MFC. Se muestra complacido con ello, y comenta que los principales cambios son a la librería MFC así como al lenguaje mismo.

Las siguientes son las nuevas características.

  1. Mejoras a la librería MFC. Estas incluyen la incorporación de diversos controles como el Ribbon de la Fluent UI de Microsoft Office, mejores barras de herramientas, controles como botones con imágenes y cajas de texto con botón incluido, paneles adheribles, barra de Outlook y muchos más.
  2. Un diseñador para poder crear Ribbons. Así como diseñamos menús o barras de herramientas, ahora podemos diseñar ribbons.
  3. Un manejador de estilos para que el tema de la ventana se vea normal, como el de Office (en azul, negro, gris), como el de Visual Studio o como el de Windows 7.
  4. MFC Restart Manager. Un administrador para que las aplicaciones se recuperen (y recuperen documentos) cuando una aplicación se termina inesperadamente, guardando el documento sin salvar. Similar a como funciona Word o Visual Studio.
  5. El class wizard ha regresado.
  6. Nueva clase: CTaskDialog que se puede utilizar en lugar de los mensajes comunes disparados con AfxMessageBox. Solo funciona para Windows Vista en adelante.
  7. Actualizaciones al lenguaje C++: deducción de tipo de dato (“auto”), obtención del tipo de dato de una expresión (“decltype”), funciones lambda, referencias a un r-valor (valor asignado), puntero nulo (“nullptr”)

Aunque los avances presentados son importantes, también hay cosas que decir al respecto. En mi opinión:

  1. Las mejoras a MFC son importantes desde luego. El ribbon y demás componentes del Fluent UI son aire fresco para MFC, que no había sufrido una actualización significativa desde MFC 6.0. Además pone a MFC como la única plataforma de desarrollo soportada por Microsoft para desarrollar con el Fluent UI (ni Windows Forms ni Windows Presentation Foundation lo soportan). Pero estas actualizaciones salieron en el Visual C++ 2008 Feature Pack. Es decir, ya estaban disponibles como instalación aparte del VC2008, y para el 2010 solo las distribuyen “out-of-the-box”. Así que en otras palabras, ésto no es algo nuevo.
  2. El diseñador de ribbons está supremo. Antes era muy complicado ir creando los ribbons, con este diseñador la verdad que sí se lucieron estos tíos. ¡Gracias y enhorabuena!
  3. El manejador de estilos no es nuevo, también viene con el Feature Pack antes mencionado. Pero sí lo actualizaron para incluir el tema de Windows 7, lo cual es bueno, porque además soportan el utilizar el ribbon de Windows 7 (aquel que viene cuadradito, más minimalista, que se puede ver en mspaint o wordpad de W7).
  4. El Restart Manager de MFC supone un gran alivio cuando uno tiene que recuperar documentos. Un servicio más para nuestros usuarios de forma fácil.
  5. El class wizard nunca debió irse en primer lugar. En lo personal no me gusta utilizarlo, pero sé que hay mucha gente que sí lo utiliza. Luego entonces nunca debió desaparecer.
  6. Con Visual C++ 2008 podíamos utilizar un control nativo de Vista para hacer esto. Esta clase encapsula de mejor forma dicho control y lo hace extremadamente útil, ya que al usuario hay que proveerlo con mucha información cuando tiene que hacer decisiones importantes. Buen punto.
  7. Estas actualizaciones no son otra cosa que la incorporación de algunos puntos de C++0x. Está bien que lo hagan, pero el draft de C++0x todavía no queda completamente aprobado, así que tendremos que esperar a otra liberación de Visual C++ para poder tener la versión final de la nueva versión de C++. Sin embargo, bienvenido sean “auto” y “decltype” ya que ayudarán mucho en lo que a MFC se refiere.

Al final me parece que Visual C++ todavía queda a deber. Es cierto que el Feature Pack es algo muy bueno, solo que es una lástima que sigan sin cambiar muchas cosas de MFC que tienen pendientes. En lo personal me gustaría ver una buena librería para utilizar servicios web (sé que existe la Windows Web Services API pero me gustaría ver más integración con Visual C++) y una buena librería para XML (sé que existe MS-XML como componentes COM, pero distan mucho de ser fácilmente utilizables). ¿O qué tal mejorar las clases de ODBC para quitarle varias de las limitantes que tienen? Además muchos de las nuevas características son refritos del Feature Pack. Y por no mencionar que quitaron el soporte ISAPI para desarrollar sitios web con C++, ATL Server. Ojalá lo vuelvan a habilitar.

Pero al menos vamos por buen camino. Espero fervientemente que para la próxima versión Microsoft siga impulsando el desarrollo nativo, de la misma forma en que lo hacía cuando salió Visual C++ 6.

Categorías:C++, Noticias, Visual Studio Etiquetas:

Cómo detectar fugas de memoria con Visual C++


Fugas de memoria (memory leaks), cosas horribles del mundo, uno de los más grandes enemigos a los que el programador de C++ se puede enfrentar.

Todos las conocemos, ¿verdad? Ubicas memoria dinámica y olvidas desubicarla:

int main()
{
  int* p = new int();

  return 0;
  // no se elimina p con un delete, así que
  // aquí hay una fuga de memoria
}

 

Obvio el caso anterior difícilmente ocurriría en la vida real. Era un ejemplo simple. En esa vida real cosas mucho más complicadas pueden ocurrir. Y encontrar en dónde se encuentra la fuga es una tarea titánica.

Visual C++ provee algunas herramientas para poder detectar fugas de memoria. Cuando corremos nuestro programa en modo de depuración.

En primer lugar, cuando trabajamos con ATL o MFC, tenemos una macro llamada DEBUG_NEW que sirve para dar información sobre el archivo y línea donde se invoca la creación dinámica. Para ello tendríamos que hacer algo como:

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

e incluirlo en todos los archivos. DEBUG_NEW lleva un registro de todos los objetos creados de forma dinámica, con el nombre del archivo y la línea de donde fueron instanciados. Cuando el programa termina, se llama al Object Dump de todos los objetos (en el caso de aquellos que deriven de CObject, se manda a la versión de CObject::Dump), lo que hace que se muestre información en la ventana de "Output" del IDE de Visual C++. Cuando hay un memory leak, así se presentará.

memoryleak

En la figura anterior les pongo un ejemplo. Corrí mi programa y al cerrarlo me detectó una fuga de memoria. En el output podemos ver los "dumps" o volcado de memoria que hace el IDE (en mi caso, Visual C++ 9). En particular, notamos que el primer volcado me lo redirecciona al archivo lookupoptions.cpp. Esto es gracias a que emplée DEBUG_NEW como indiqué anteriormente. Por ello, al hacer doble click me lleva directamente a donde se ubicó el elemento.

Por supuesto el saber dónde se generó el objeto es una parte del problema. Pero no siempre resulta obvio. Por ejemplo, en la figura anterior se crea un objeto con new y se agrega a una colección. Ésta se usa a lo largo de la existencia de una ventana hija y posteriormente la colección se encarga de eliminar todos los objetos que contenga. Por lo que la eliminación del objeto está en otra parte del código, posiblemente sin estar relacionada. Si el problema no es ubicar el objeto en memoria, sino desubicarlo.

Para poder detectar esto, normalmente tenemos que saber bajo qué condiciones se está creando nuestro objeto. En el ejemplo anterior, el IDE marca la clase que genera el objeto, pero no marca bajo qué condición se crea (i.e. qué otro objeto mandó crear la colección antes mencionada). ¿Cómo podríamos saberlo? Un breakpoint sería buena opción. Pero mejor aún, un breakpoint bajo las condiciones en las que se da la fuga. Pues bien, MFC / Visual C++ provée un mecanismo para hacer esto.

Cada objeto que se crea de forma dinámica tiene un ID, que representa su número de creación. Cuando se hace el volcado de la memoria para detectar la fuga, se imprime este ID entre llaves. En la figura anterior se muestran encerradas en un círculo rojo. En este caso, el objeto fue el 27620° en ser creado. Por otro lado, existe una función, _CrtSetBreakAlloc que toma como parámetro un número que es precisamente el número de objeto creado (en el caso del ejemplo anterior, 27620). Esta función hace que cuando se vaya a crear el objeto cuyo número es el del parámetro (i.e. 27620) se mande llamar a AfxDebugBreak, lo cuál actúa como un breakpoint. En ese momento, podemos revisar el stack y demás variables para saber cuál es el entorno y contexto de la creación de mi objeto, facilitando la caza del bug.

Luego entonces, basta mandar llamar a _CrtSetBreakAlloc al mero inicio del programa (main si estamos en consola, WinMain si es una aplicación para Windows, y CWinApp::InitInstance si trabajamos con MFC.

Me pareció interesante, ya que recientemente tuve este problema y pude resolverlo de forma fácil así. MSDN tiene éste artículo que viene con técnicas más avanzadas para detectar fugas de memoria, y éste artículo que habla sobre lo que les acabo de comentar.

Espero esto ayude a eliminar esas cosas horribles llamadas Fugas de Memoria.

Categorías:C++, Cómo hacer, Visual Studio Etiquetas: