Questa è una vecchia versione del documento!
Indice
Esercitazione 2
Esercizio 1: funzioni rientranti (tokenizer_r)
Si consideri il seguente programma:
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "use: %s stringa1 stringa2\n", argv[0]); return -1; } char* token1 = strtok(argv[1], " "); while (token1) { printf("%s\n", token1); char* token2 = strtok(argv[2], " "); while(token2) { printf("%s\n", token2); token2 = strtok(NULL, " "); } token1 = strtok(NULL, " "); } return 0; }
Cosa c'e' che non va? Come si puo' correggere ?
(Suggerimento: leggere con attenzione il man
di strtok
).
NOTA: se si utilizza l'opzione -std=c99
, per evitare i warnings del tipo “implicit declaration of function X” aggiungere la seguente opzione di compilazione “-D_POSIX_C_SOURCE=200112L”, oppure inserire la seguente define prima del primo include:
#define _POSIX_C_SOURCE 200112L
Esercizio 2: numeri random
Generare N
numeri casuali interi nell'intervallo [0,K[
utilizzando le funzioni rand_r()
ed srand()
. N e K sono definiti con delle opportune #define
. Calcolare il numero di occorrenze c_i
di ciascun intero i
nell'intervallo [0,K[
e stamparle sullo standard output.
Esercizio 3: valgrind
Verificare la correttezza degli accessi in memoria utilizzando valgrind
dei programmi realizzati nell'esercizio 1 e 2. Verificare che non ci siano memory leaks all'uscita del programma.
Valgrind permette, fra l'altro, di capire se le variabili sono inizializzate prima del loro uso, se accediamo a memoria gia' deallocata o mai allocata o a zone non inizializzate.
Passi:
- compilare il file da verificare con opzione
-g
per includere le informazioni di debugging (anche se non è strettamente necessario). - eseguire il programma con
valgrind
nel modo seguente :
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.
Se si specifica l'opzione –leak-check=full
(attenzione al doppio trattino), valgrind fornirà dettagli per ogni blocco di memoria che non è più raggiungibile o che pur essendo raggiungibile non è stato liberato, dando anche l'informazione di dove il blocco è stato allocato.