Indice

Esercitazione debugging

I lucidi introduttivi per il debugging. Eseguire con i debugger ddd e/o gdb e trovare il problema nei seguenti programmi.

Esercizio 1: Aggiornamenti

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define N 5
 
/* globali */
int z[N+1];
int a[N-1];
int i;
 
void aggiorna (int k);
 
int main(void)
{
  srand(time(NULL));
  i=0;
  while (i<N)
    {
 
      aggiorna(i);
 
      printf("iterazione %d\n",i);
      i++;
    } 
  printf("exiting ...\n"); 
  return 0;
}
 
void aggiorna (int k) {
  a[k]=rand()%2;
  z[k+1]=a[k];
}

in pratica il codice, salvato in “file.c” compilato con

gcc -Wall -pedantic -o ese file.c

ed eseguito con

$ ./ese

va inspiegabilmente in ciclo all'interno del ciclo. Per eseguire in modalita' interattiva di debugging:

* oppure in

$ gdb ./ese

a questo punto e' possibile fermare il programma durante la sua esecuzione, ispezionare le variabili etc..

Esercizio 2: Debuggare codice altrui ...

Per i solutori piu' che abili. Trovare l'errore…

#include<stdio.h>
#include<string.h>
 
 
void leggi( char *[]);
void stampa(char *[], int);
 
int main()
{
  char *a[3]={"alberello","rosea","roma"};
  char *b = NULL;
 
  leggi(a);
 
  return 0;
 
}
 
void stampa(char *arch[],int sizeA)
{
  int i;
 
  printf("i loro indirizzi sono:\n");
 
  for(i=0;i<sizeA;i++)
    printf("%p\n",(void*)&arch[i]);
 
 
}
 
void leggi(char *archivio[]){
  int i;
  int size=strlen(*archivio);
 
  for(i=0;i<size;i++)
    printf("%s\n",archivio[i]);
 
 stampa(archivio, size);
}

Esercizio 3: (avanzato) Verificare i memory leak con ''mtrace'' (solo per chi ha mcheck.h/mtrace già installato)

Con riferimento al main sviluppato per l'esercizio precedente verificare che tutta la memoria allocata venga deallocata prima dell'uscita dal main().

Per la verifica si utilizzi la funzione mtrace e l'utility mtrace, questi strumenti tracciano le azioni di allocazione e deallocazione di memoria compiute dal programma per verificare la presenza di memory leak cioe' memoria non deallocata.

Per fare questo procedere come segue:

bash$ gcc -Wall -pedantic -g -o prova main.c 
bash$ export MALLOC_TRACE=./mtrace.out
bash$ ./prova
bash$ mtrace ./prova ./mtrace.out 

questo rispondera' No memory leaks se tutta la memoria e' stata deallocata o fornira' indicazioni su dove e' stata allocata la mamoria rimasta da deallocare.

Esercizio 4: (avanzato) verificare gli accessi in memoria: valgrind

Verificare la correttezza degli accessi ai puntatori dello heap compiuti dalle funzioni su liste sviluppate negli esercizi precedenti utilizzando valgrind. Questo strumento permette fra l'altro di capire se tutte le variabili sono inizializzate prima del loro uso, se accediamo a memoria gia' deallocata o mai allocata e situazioni similari

Per fare questo procedere come segue:

bash$ gcc -Wall -pedantic -g -o prova main.c
bash$ valgrind ./prova

in questo modo, a schermo verranno riportare le infrazioni rilevate. Ad esempio, invalid read o invalid write sono accessi in lettura o scrittura a memoria non allocata o gia' deallocata.

valgrind contiene moltissime opzioni, invitiamo gli studenti interessati ad esplorarle partendo dalsito.