Detectando fugas de memoria: Visual Leak Detector

Ésta librería me la encontré por casualidad un día navegando por Internet, y curiosamente unos meses más tarde tuve que recurrir a ella. Si has desarrollado programas para Linux usando C o C++, seguramente tarde o temprano habrás recurrido a usar Valgrind, el entorno que emula una arquitectura x86 y detecta todos los usos indebidos de la memoria.

Pues bien, Visual Leak Detector es una librería que, al incluirla en nuestro proyecto, nos muestra toda la información (por medio de la consola de Visual Studio o, si lo deseamos, con salida a un fichero de texto) sobre la memoria no liberada (memory leaks) con una precisión pasmosa. Y ahora, un ejemplo de su uso:

  1. Descargamos el instalador.
  2. Lo ejecutamos y procedemos a instalarlo en el lugar que más adecuado nos parezca. Muy seguramente, durante el proceso de instalación nos preguntará si deseamos añadir la ruta a la librería “vld.dll” al path automáticamente. Aceptamos y continuamos.image
  3. Ya esta listo para usar. Si queremos, en la última pantalla podemos visualizar la documentación.image
  4. Ahora hay dos opciones para que Visual C++ reconozca el archivo de cabecera y la librería; la primera consiste en ir a la carpeta donde hemos instalado Visual Leak Detector y copiar los directorios “include” y “lib” a la carpeta “VC” existente dentro de nuestra instalación de Visual Studio. Sin embargo, este método puede considerarse poco más que una chapuza, así que vamos a hacer las cosas bien y lo vamos a configurar desde dentro de nuestro proyecto.
  5. Ejecutamos el Visual Studio y creamos una nueva aplicación de consola de Visual C++. En el diálogo del asistente seleccionamos la sección “Application Settings” y activamos la casilla “Empty project”. No queremos que Visual C++ nos añada archivos que puedan dar lugar a confusión (como las cabeceras precompiladas).image

    image

  6. Ahora es el turno de configurar las nuevas rutas de inclusión del proyecto. Nos vamos al menú “Project” y seleccionamos la última opción, “<Nombredeproyecto> Properties…”. Navegamos el árbol de opciones seleccionando “Configuration Properties / C/C++ / General” y pinchamos en el campo “Additional Include Directories” de la lista de opciones de la derecha. Veremos que aparece un botón con unos puntos suspensivos que nos abrirá una nueva ventanita, en la que pulsando el botón con el icono de una carpeta nos permitirá especificar un nuevo directorio para añadir a la lista. Añadimos el subdirectorio “include” dentro de nuestra instalación de Visual Leak Detector y pinchamos en “OK”.image

    image

  7. Ahora en el árbol de opciones de la izquierda nos desplazaremos hasta “Configuration Properties / Linker / General”. Aquí, con el campo “Additional Library Directories” tenemos que hacer exactamente lo mismo que en el punto anterior, solo que en lugar de agregar el directorio “include”, ésta vez seleccionaremos “lib”.image
  8. Por último, vamos a “Configuration Properties / Linker / Input” y en “Additional Dependencies” escribimos “vld.lib”. De ésta manera le decimos al enlazador que si encuentra algún símbolo desconocido, busque información en dicha librería para resolver las dependencias.image
  9. Ahora ya solo queda comprobar el funcionamiento de la librería. Vamos a añadir un nuevo fichero de código fuente a la carpeta “Source Files” de nuestro proyecto, llamado “main.cpp”, y vamos a teclear el siguiente código:image
  10. Y procedemos a compilarlo y ejecutarlo. Aparecerá la ventana de consola con la ejecución de nuestro programa y podremos finalizarla. Aparentemente todo funciona bien, pero si vamos a “View / Output”, habilitaremos la ventana en la que podremos ver la salida del Visual Leak Detector. Aquí nos informa que se ha producido un memory leak, concretamente de 100 bytes, y el inicio del problema está en la línea 8 de “main.cpp”.image
  11. Podemos comprobar que en dicha línea hemos realizado una reserva de memoria con el operador new, pero luego no la hemos liberado. Vamos a subsanar el error y a comprobar qué ocurre esta vez tras la ejecución:image

En efecto, Visual Leak Detector notifica que no hay ninguna fuga de memoria y que todo ha funcionado correctamente. Ahora es el turno de emplearlo en vuestras propias aplicaciones 😉

Uso de la función “main” en C/C++

Escribo este post porque según las estadísticas, en los últimos días he recibido bastantes visitas a través de buscadores intentando encontrar una explicación al uso de la función main en C/C++ (seguro que no es la única sorpresa que me da haber escogido este nombre para el blog…). Qué menos que agradar a mi escaso público y ganarme unos cuantos lectores, así que voy a escribir algo útil de una vez y explicaré todo lo profundamente posible esta función.

En primer lugar, la función nunca debe ser declarada como void. Ésta es una mala práctica que se suele cometer, sobre todo al comenzar la andadura con la programación (lo admito, ¡yo también lo hacía al principio!); si bien algunos compiladores lo aceptan, los más estrictos se quejarán en forma de warning o error. Así que hay que usar int para declarar el tipo, o incluso también se puede obviar, porque el compilador le asignará este tipo por defecto.

void main() // MAL: algunos compiladores se quejarán
{
}

int main() // CORRECTO: la forma adecuada de hacerlo
{
}

main() // CORRECTO: no es la mejor, pero los compiladores que sigan el estándar la darán por buena
{
}

Bien, ahora atacaremos los valores de retorno. Esto es muy sencillo; como hemos declarado la función del tipo int, al llegar al final de su ejecución tendremos que devolver un valor. Normalmente se devuelve 0 para indicar que el programa ha finalizado correctamente, y cualquier otro valor para indicar una ejecución anormal. Pero, si queremos ser completamente estrictos (en algunas plataformas el significado de los valores se invierte, y 0 puede significar que ha ocurrido un fallo de ejecución), emplearemos las macros EXIT_FAILURE y EXIT_SUCCESS. Como su nombre bien indica, la primera devuelve una ejecución errónea, y la segunda indica al proceso padre que todo ha ido como debería. Sus definiciones se encuentran en stdlib.h para el lenguaje C y cstdlib.h para C++.

int main()
{
  return EXIT_SUCCESS;  // El programa terminó la ejecución debidamente
}

int main()
{
  return EXIT_FAILURE;  // El programa encontró algún fallo y no pudo finalizar la ejecución correcta
}

int main()
{
  return 5;  // Valor de retorno personalizado; de esta manera podemos indicarle al proceso que invoca a nuestro programa que ha ocurrido algo determinado (por ejemplo, que no se ha llamado al programa con determinados parámetros)
}

Y por último, hablaremos de los parámetros de la función. Hasta ahora, la hemos definido sin ningún tipo de parámetros, porque según el estándar esto puede hacerse perfectamente; sin embargo, main acepta dos parámetros que se explicarán a continuación (hay que recordar que siempre es o cero o dos parámetros, en caso de emplear cualquier otro número el compilador dará warning o error, dependiendo de lo quisquilloso que sea):

  • Primer parámetro: tipo int. Por costumbre se le llama argc, diminutivo de argument count, pero se le puede llamar como se desee. Como su propio nombre indica, contiene el número de argumentos que se le pasan al programa. Hay que tener en cuenta que el primer argumento de un programa siempre será el nombre de este, de tal manera que si hacemos la siguiente ejecución

    :> miprograma param1 param2

    nuestro parámetro argc valdrá 3, y por consiguiente, si llamamos al programa sin parámetros, argc equivaldrá a 1.

  • Segundo parámetro: tipo char**. Aunque también puede especificarse como char* argv[], lo importante es indicar que estamos trabajando con un doble puntero a char, esto es, un vector de vectores de caracteres, o para simplificar, un vector de cadenas. Como se ha indicado anteriormente, el nombre más común para llamar a este parámetro es argv, contracción de argument vector, y al principio puede resultar un poco lioso lidiar con él, más aún si no se han usado punteros nunca. Así que simplemente hay que recordar que estamos trabajando con un vector de cadenas, y que cada posición (recordad, su extensión va desde 0 hasta argc-1) guarda uno de los argumentos empleados al llamar a nuestro programa. Para la ejecución de ejemplo del punto anterior, esta sería la traza de nuestros parámetros:

    argc = 3;
    argv[0] = “miprograma”;
    argv[1] = “param1”;
    argv[2] = “param2”;

Y esto es todo por hoy, como veréis tampoco es para tanto, aunque al principio se pueda atragantar. Y aprovecho para animar a todo el que llegue aquí a que formule las preguntas que quiera, intentaré ayudar en la medida de lo posible 😀

Animación de modelos 3D en XNA

Este post viene a raíz de mi participación en el concurso de desarrollo de videojuegos con XNA convocado por el Club .NET de Alicante. Me decidí por hacer un remake de un antiguo juego de arcade (no voy a dar muchos detalles hasta que acabe el plazo de entrega, tened un poco de paciencia), y aunque sopesé emplear las 2D como en el original, finalmente opté por emplear las 3D porque podría reusar bastante contenido (modelos y texturas) guardados por los rincones más dispares de mi disco duro. Además, qué leñe, el 3D mola mucho más 😀

Por defecto, XNA se queda un poco corto en cuanto al manejo de modelos se refiere. Sí, se pueden cargar y renderizar con apenas 10 líneas, pero cuando tenemos que emplear animación esqueletal, la cosa se complica y mucho. El XNA Creator’s Club tiene varios ejemplos publicados, entre ellos el Skinned Model Sample que es un buen punto de partida para hacernos una idea de lo que nos espera. Simplemente se basa en exportar el modelo desde nuestro software de modelado al formato FBX, interpretarlo con el Content Pipeline que trae incorporado el ejemplo, y el código se encarga de enviar al shader las matrices de transformación de cada vértice frame a frame, para que éste deforme su posición correctamente (este proceso se llama Matrix Palette Skinning).

¿El problema? Que es un ejemplo MUY básico. Sólo sirve para modelos con una animación, y que se repita cíclicamente. Por eso tuve que recurrir al gran amigo Google y buscar librerías con mayor funcionalidades. Así es como acabé conociendo XNAnimation y KiloWatt.

  • XNAnimation: primera candidata. Tiene un gran número de características, entre las que destacan interpolación de frames, blending de animaciones, velocidad variable y un máximo de 80 bones por modelo. Y, parece ser (aunque no puedo confirmarlo porque sólo compilé el visor de modelos básico), que también soporta attachments en los modelos, esto es, “pegar” el bone de un modelo al de otro, como por ejemplo para colocar un arma en la mano de un personaje. Como formato de entrada emplea FBX estándar, lo cual se llega a agradecer porque no hace falta andar toquiteando cosas en el software de modelado. Ah, y en caso de múltiples animaciones, éstas se definen en un fichero XML, que puede editarse fácilmente. La pega es que tuve que descartarla porque los modelos que necesitaba usar tenían esqueletos algo extraños y se corrompían al renderizarlos 🙁
  • KiloWatt: al final me tuve que decantar por ésta, y tampoco me ha dejado mal sabor de boca. Emplea el formato X, pero con unas cuantas restricciones que al principio se hacen incómodas. Sólo es compatible con modelos exportados con el plugin kW X-port, disponible únicamente para 3DS Max a partir de la versión 9. Además, dentro del propio Max hay que hacer algunas modificaciones a nuestro modelo para que se exporte correctamente:
    • Establecer las texturas que usamos en nuestro  modelo como materiales del tipo “DirectX Shader”, y asignarle el shader “diffusexparent.fx” existente en la carpeta “tools/AnimationViewer/Content” del proyecto de KiloWatt.
    • Aumentar el valor del campo “Fog Distance” hasta 10000 aproximadamente, para evitar que la niebla sea muy espesa y distorsione el modelo.

materiales

    • Unificar todas la animaciones del modelo en un mismo fichero, Y, además, el primer frame debe ser el de referencia; esto es, el frame 0 contendrá el modelo sin ninguna transformación (pose de “brazos en cruz”), del 1 al 10 será una animación, del 11 al 25 otra, etc.
    • Y por último, ya sólo nos queda exportarlo (otro punto a favor, nos coloca en la misma carpeta el fichero final, junto con el shader empleado y los materiales empleados redimensionados a un tamaño múltiplo de 2), integrarlo en nuestro proyecto y asignarle el Content Processor llamado “Animation Processor – KiloWatt”).

exporter

Eso es todo por hoy, quizá el artículo me ha quedado un poco “difuso”, pero en cuanto acabe el juego y lo entregue, continuaré destripándolo para que sirva de referencia a todo aquel que lo necesite 😉