Análisis dinámico y estático

Todos cometemos errores, en la programación un paréntesis demás puede provocar resultados impredecibles…

Principalmente vamos a ver un poco los métodos que tenemos para analizar si nuestro código contiene errores.
Nos basamos en dhewm3, código escrito en C++, por lo que nos sirve perfectamente.
Hay herramientas para Java, python, etc. Pero vamos de a poco

Análisis estático y análisis dinámico

La diferencia entre ambos métodos es sustancial.
El análisis estático consiste en realizar chequeos en momento de compilación (o incluso antes), por lo que nos puede notificar si tenemos un error de lógica o simplemente nos mareamos con un “copy-paste”.
Para comenzar, les sugiero probar con Cppcheck. Es gratuito y bastante claro en los mensajes que devuelve.
El método de análisis dinámico por otro lado consiste en analizar código ya compilado. Resulta muy útil para encontrar desbordes de memoria, entre otras cosas.
Uno de los representantes mas famosos de este tipo de análisis, es el Valgrind, pueden aprender de el siguiendo los primeros pasos, publicados en su web.

Ejemplo de análisis estático

Veamos como se emplea el método en practica. Primero ejecutamos cppcheck -j 4 -v /directorio/con/codigo/c 2>cppcheck.log, así tenemos el log con detalle a analizar.
A la salida vamos a tener un error por linea, analicemos algunos para ver si los podemos arreglar

Numero incorrecto de parametros:

[neo/idlib/Heap.cpp:1315]: (error) fprintf format string has 5 parameters but only 4 are given

Vamos a la linea 1315 del archivo neo/idlib/Heap.cpp, lo que observamos es:

fprintf( f, "size: %7d B: %s, line: %d [%s], call stack: %s\r\n", b->size, Mem_CleanupFileName(b->fileName), b->lineNumber, dump );

Claramente se le pasan 4 argumentos en lugar de 5, pero si el código no es nuestro, tenemos que averiguar que intención perseguía el programador. En nuestro caso podemos resolver el tema así:

fprintf( f, "size: %7d B: %s, line: %d [%s]\r\n", b->size, Mem_CleanupFileName(b->fileName), b->lineNumber, dump );

Posible señalamiento nulo:

[neo/game/Actor.cpp:2416]: (error) Possible null pointer dereference: sound

Vamos al archivo, función culpable del error:

void idActor::PlayFootStepSound( void ) {
        const char *sound = NULL;
        const idMaterial *material;if ( !GetPhysics()->HasGroundContacts() ) {
        return;
    }// start footstep sound based on material type
    material = GetPhysics()->GetContact( 0 ).material;
    if ( material != NULL ) {
        sound = spawnArgs.GetString( va( "snd_footstep_%s", gameLocal.sufaceTypeNames[ material->GetSurfaceType() ] ) );
    }
    if ( *sound == '\0' ) {
        sound = spawnArgs.GetString( "snd_footstep" ); // Linea 2416
    }
    if ( *sound != '\0' ) {
        StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
    }
}

Aquí el problema es que probablemente sound sea NULL y lo intentamos usar, agregamos una comprobación justo antes:

if (sound){
    if ( *sound == '\0' ) {
        sound = spawnArgs.GetString( "snd_footstep" );
    }
...

Resource leak:

[neo/sys/win32/SDL_win32_main.c:247]: (error) Resource leak: newfp

Viendo la linea, recurrimos a la referencia freopen para corroborar que necesitamos emplear un fclose() en algún lado:

newfp = freopen(stderrPath, TEXT("w"), stderr); // linea 247

Con solo agregar fclose(newfp); – se resolveria

Algunos enlaces a problemas genéricos que pueden surgir:

Mismatching allocation and deallocation
Resource leak
Possible null pointer dereference: X – otherwise it is redundant to check if X is null at line Y

Claro, no nos olvidemos de chequear las alertas del compilador:
Comparing values of different enumerated types [-Wenum-compare]
Array subscripts out of bounds [-Warray-bounds]
X is used uninitialized in this function [-Wuninitialized]

Deja un comentario

Para proteger el blog de SPAM, le pedimos que complete la tarea:WordPress CAPTCHA