Indice

Esercitazione 2

Dove si sperimenta qualche tool e si approfondiscono alcune caratteristiche del C sequenziale: errno, perror …

Esercizio 1: mtrace

Verificare gli accessi in memoria compiuti dalle funzioni su liste di interi della libreria libList.a utilizzando 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 -lList -L.
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 2: verificare gli accessi in memoria: valgrind

Verificare la correttezza degli accessi ai puntatori compiuti dalle funzioni su liste di interi della libreria libList.a 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.

Esercizio 3: lettura-scrittura su file con stdio

Scrivere un programma C che legge una sequenza di studenti da file anagrafe_studenti. Ogni studente e' memorizzato su file in una singola linea contenente tre stringhe di caratteri separate da ':' e terminata da '\n' secondo il formato

cognome:nome:numero_di_matricola

quindi ad esempio

...
Rossi:Mario:234445
Bixio:Nino:435678
Garibaldi Giuseppe 787899
...

Il programma memorizza i dati relativi a ciascun studente in un array di strutture di tipo studente opportunamente definito e li stampa in ordine alfabetico.

Suggerimento: Per la lettura da file usare fscanf() con una opportuna stringa di formattazione oppure fgets() per leggere fino al primo \n e strchr() per localizzare i caratteri separatori :

Esercizio 4: lettura-scrittura su file passato come argomento

In C e' possibile accedere agli argomenti passati sulla linea di comando tramite la struttura argv che punta ad una array di stringhe. Per farlo, dichiarare il main() di tipo

int main (int argc, char* argv[]) {
...
}

in questo modo argc conterra' il numero di argomenti passati sulla linea di comando, argv[0] il nome dell'eseguibile e argv[1], argv[2], … i vari argomenti passati sulla linea di comando. Ad esempio, se ho compilato il mio programma in un eseguibile prova

bash$ ./prova pippo pluto paperone

argc varra' 3, argv[1] conterra' pippo, argv[2] pluto ed argv[3] paperone.

Si chiedere di modificare l'esercizio 3 in modo da realizzare il comando leggistud

bash$ leggistud nome_file

che ordina gli studenti contenuti nel file nome_file passato come primo parametro. Fare in modo di stampare un opportuno messaggio di uso se invocato con un numero di parametri diverso da 1.

Esercizio 5: Manipolare ''errno'' e uso di ''perror()''

In C, la maggior parte delle funzioni di libreria che segnalano un errore settano anche la variabile globale errno con dei codici definiti da diversi standard. I codici sono valori interi, definiti da opportune macro. Per vadere il loro valore eseguire

bash$ man errno

Dopo l'esecuzione di una funzione di libreria che imposta errno e' possibile chiamare la funzione di libreria perror() che ispeziona il valore di errno e trasforma il valore numerico in un messaggio testuale comprensibile all'utente (vedere man perror per il suo uso). E' possibile manipolare errno da programma includendo l'header errno.h con

#include <errno.h>

L'esercizio richiede di essegnare a errno i valori EINTR EPERM EBUSY e stampare i corrispondenti messaggi di errore usando perror().