22 nov 2011

Test de cobertura de código con gcov

A la hora de determinar la validez del código programado, resulta útil analizar el mismo para determinar si las diferentes partes del mismo son todas probadas al pasar los test (una buena forma es hacer desarrollo guiado por test o TDD). Para ello, las herramientas GNU nos proporcionan gcov, que nos dará información diversa sobre éste tipo de análisis.
Existe diversa información a analizar cuando se realiza un análisis de cobertura de código (http://en.wikipedia.org/wiki/Code_coverage), aunque aquí nos limitaremos a anotar la manera de utilizarlo de forma mas básica.

Para utilizar gcov, deberemos compilar nuestro programa/as añadiendo las opciones -fprofile-arcs -ftest-coverage a la compilación (podemos añadirlo a CFLAGS p. ej.)

¡¡¡Importante!!! Si utilizamos alguna directiva de optimización de código (p. eje -O2) gcov no nos dará información útil, ya que las optimizaciones modificarán el análisis. Por tanto, dichas opciones han de ser eliminadas en la compilación para la cobertura de código.

Una vez compilado el programa, obtenemos un archivo .gcno con la información que necesita gcov.

A continuación, si ejecutamos el programa, se nos creará un archivo .gcda con los datos de la ejecución para interpretarlos con gcov.

Lo siguiente sería invocar a gcov con las opciones que necesitemos, por ejemplo:

#gcov programa.c

Ésto creará un archivo programa.c.gcov con toda la información sobre la cobertura del código. Si lo editamos, podemos ver que al lado de cada línea nos indica el número de veces que se ha ejecutado la linea en cuestión (y si se ha ejecutado claro). De esta forma podemos saber que partes del código han sido probadas y cuáles no.

Otra opción interesante es invocar gcov con la opción -b, que nos dará información probabilistica sobre las sentencias condicionales (análisis MC/DC y similares como se puede ver en el artículo de la wikipedia)

Por último, es posible generar informes html a partir de ésta información utilizando el script lcov en vez de gcov, inicialmente pensando para realizar estas tareas sobre el kernel de Linux, pero útil también para aplicaciones de usuario normales, aunque no genera información probabilistica sobre las sentencias condicionales.

La manera de utilizarlo es la siguiente:
  • Capturar la información.
#lcov -c -d directorio_de_trabajo -o nombre_archivo_salida.info
  • Generar html
#genhtml nombre_archivo_salida.info -o directorio_destino_html


Para usarlo en baterías de test, puede ser necesario utilizar las capacidades que tiene de combinar datos de distintas ejecuciones, para lo cual es recomendable ver man lcov.


10 mar 2011

Mezclar enlazado dinámico y estático C

A veces, en un programa en C, es necesario enlazar con bibliotecas estáticas, lo cual no es un problema, salvo que también necesites enlazar con otras dinámicas.
Por defecto, cuando invocamos el enlazador desde gcc, el enlazado se hace de manera dinámica, aunque podemos forzarlo con la opción -static para que se haga estática. De ésta forma, se incluirán en el ejecutable los códigos objeto de las funciones llamadas en él.
Pero, ¿y si lo que queremos es enlazar algunas bibliotecas de forma dinámica y otras de forma estática?
Pues la solución es simple, aunque creo que no óptima:

 -Wl,--whole-archive -lbiblio_estatica ...
-Wl,--no--whole-archive -lbiblio_dinamica ...
Con lo que mediante -Wl le decimos a gcc que le pase lo siguiente al enlazador ld.

Y digo que creo que no es óptima porque según el manual del enlazador ld, éstas opciones hacen que se incluya en el ejecutable los archivos completos que se indican a continuación, por lo que se introducirá código que el programa no use (o eso es lo que yo entiendo).

Después le pasamos la opción que anula la configuración de incluir todos los archivos

27 ene 2011

VIM: Elminar ^M en archivos de texto

En ocasiones, cuando abrimos archivos de texto plano con vim procedentes de "otros" sistemas operativos, nos encontramos con unos caracteres molestos al final de cada línea.

Para eliminarlos, existe un método muy sencillo desde el propio vim, ahí va la receta:

abrimos el archivo:

vim nombre_archivo.xxx

En modo comando usamos:

:%s/Ctrl+V,Ctrl+M//

"et voila"

esto nos puede servir para otras muchas sustituciones, ya que "%" significa "en todo el documento", y la "s" nos permite sustituir.