Indice

FAQ

Ossia Frequently Asked Questions.

FRAM 3: Esiste un modo semplice per gestiore i timeout in permserver ?

Si, un modo semplice per gestiore i timeout per l'aggiornamento dell'albero e' integrarli con la gestione dei segnali usando un thread apposito e la funzione sigtimedwait(). Con questa funzione e' possibile settare un timeout pari a K sec. Se la funzione ritorna -1 errno==EAGAIN il timeout e' trascorso senza l'arrivo di segnali (quindi si puo' ricostruire l'albero) altrimenti il valore ritirnato e' il sagnale arrivato (vedi man sigtimedwait).

FRAM 3: Si usano socket AF_UNIX : Refuso nella descrizione ztl0809.pdf

Nella descrizione c'e' un errore di stampa che chiede di usare i socket AF_INET per comunicare fra server e client. Si tratta di un errore di stampa in quanto nel progetto devono essere usati esclusivamente i socket AF_UNIX.

FRAM 1: Che problema ha il permesso .....?

"CN4456K 12/12/2008-13:30 13/12/2008-14:30", /* alfanumerico */

Le targhe sono composte da due caratteri maiuscoli, tre cifre e altri due caratteri maiuscoli, quindi il penultimo carattere della targa non puo' essere 6.

FRAM 1: Se rimuovo l'ultimo permesso di una targa devo rimuovere anche il nodo corrispondente?

Si, se la removePerm() cancella l'ultimo permesso il nodo non fornisce piu' informazione e deve essere rimosso e deallocato.

Problemi con bashdb

Usando una distribuzione Linux recente (ad esempio Ubuntu 8.04, 8.10, o comunque distribuzioni che forniscaono bash in versione 3.2 o superiore) lo script di debugging bashdb non funziona. Fortunatamente le stesse distribuzioni forniscono lo script gia` pacchettizzato in una versione aggiornata. Ad esempio, per installarlo sotto Ubuntu o Debian basta dare il comando

sudo aptitude install bashdb

quindi lanciarlo normalmente con

bashdb nome_script

(vedete anche man bashdb e l'help che ottenete digitando “h” al suo prompt).

Debuggare programmi con piu` processi

E` possibile usare GDB per debuggare programmi multiprocesso / multithread come indicato nella documentazione qui e qui. E` possibile usare i comandi indicati anche in DDD, scrivendoli manualmente nel prompt del GDB in basso nella schermata.

Uso di GDB da emacs

E' possibile usare il debugger GDB da emacs. Questo permette di seguire interattivamente il flusso di esecuzione in due sottofinestre dell'editor. Per attivarlo:

Perche` mtrace mostra una stringa esadecimale al posto del nome del file?

R: Questa situazione si puo` verificare per tre ragioni differenti:

  1. il file al quale mtrace vorrebbe fare riferimento e` stato compilato senza opzione di debug (-g);
  2. il file al quale mtrace vorrebbe fare riferimento e` stato compilato con il compilatore c++ (g++);
  3. il file al quale mtrace vorrebbe fare riferimento e` una libreria presente sul sistema (libc, libm…).

Quest'ultima situazione si verifica nel caso in cui siano state usate funzioni di libreria all'interno delle quali viene allocata della memoria (come la strdup()). La memoria, anche se allocata da funzioni di libreria, deve essere sempre liberata usando una free().

char *p;
char s[6] = "pippo";
 
p = strdup(s);
/* ... */
free(p);

Ho la quota disco piena e non riesco a salvare i miei files

R: Molto probabilmente la causa di buona parte dei problemi di quota e` dovuta all'utilizzo di eclipse come ambiente di sviluppo. la prima cosa da fare e` vedere quanto spazio e` utilizzato inutilmente da eclipse. (si assume che l'utente lavori nella directory workspace)

(susanna):==>du -sh ~/workspace/.metadata
12.4M   /home/susanna/workspace/.metadata

a questo punto si puo` procedere con l'eliminazione. ATTENZIONE: state attenti ad inserire questo comando esattamente cosi`, altrimenti rischiate di cancellare tutti i vostri files

(susanna):==>rm -fr ~/workspace/.metadata

Oppure

Si puo' cancellare la cache di Mozilla mediante l' utilizzo dello script rimuovicache.sh fornito dai docenti:

(susanna):==> wget http://www.cli.di.unipi.it/~bartolin/rimuovicache.sh
(susanna):==> chmod +x rimuovicache.sh
(susanna):==> ./rimuovicache.sh

Oppure:

(susanna):==> ./rimuovicache.sh --help 

Per un mostrare le opzioni dello script.

Perche' non fa loggare piu' tramite interfaccia grafica?

R: Molto probabilmente e' stata raggiunta la quota disco. Per risolvere il problema e' sufficiente digitare [CTL+ALT+F1], effettuare il login in modo testuale e seguire i passi della FAQ “ho la quota disco piena e non riesco a salvare i miei files”.

Come faccio ad utilizzare la bash se la mia shell di default e' la csh/tcsh?

R: Per ragioni “storiche” il CDC usa la csh/tcsh come shell default di login e non permette di cambiarla. Nel prossimo futuro verra' effettuato un adeguamento allo standard di fatto attuale fornendo la bash come shell di login e permettendo a chi non ce l'ha di sceglierla. Per sperimentare con la shell bash basta digitare

(susanna):==> bash
bash-2.05b$

oppure

(susanna):==> exec bash
bash-2.05b$

in entrambi i casi la vostra shell mandera' in esecuzione una bash con cui potrete interagire. Alla fine potete uscire con

bash-2.05b$ exit
exit
(susanna):==>

oppure EOF (CTRL-D).

Per non avere un ambiente “nudo” si consiglia di salvare i seguanti script di configurazione (esattamente con questi nomi) nella vostra home directory (ad esempio, ~susanna/ per l'utente susanna):

.bashrc .bash_profile .bash_aliases

In questo modo otterrete un prompt piu' significativo e un ambiente piu` gradevole:

(susanna):==> bash
susanna@aulaa:~$

In particolare aggiungendo ulteriori comandi di alias al terzo script potete personalizzare la shell creandovi i vostri alias usuali per i vari comandi (es, “rm -i” per “rm”, o “h” per “history”).

NOTA BENE: I sistemisti sconsigliano vivamente di mettere il comando exec bash direttamente nei file .login o .cshrc perche' questo potrebbe interferire negativamente con altri settaggi standard dei vostri ambienti, in particolare quello grafico.

Ho provato ad eseguire il programma digitando a.out

nella directory che lo contiene ma il risultato e' stato

bash: a.out command not found

R: La variabile di ambiente ambiente PATH non contiene la directory corrente (“.”): per eseguire il programma basta fornire il parth name completo dell'eseguibile, ad esempio quello relativo:

$ ./a.out

Per risolvere il problema si deve aggiungere la directory corrente alla variabile PATH della shell, nella bash basta dare il comando:

$ export PATH=$PATH:. 

o nella csh/tcsh

% setenv PATH ${PATH}:.

Per vedere il valore del PATH

$ echo $PATH

per capire che shell stiamo utilizzando

$ echo $SHELL

Per non dover ripetere il comando export/setenv ogni volta che aprite una finestra dovrebbe essere sufficiente aggiungere il comando come una riga dello script ~/.bashrc (bash) o ~/.cshrc (csh/tcsh).

Come posso ottenere informazioni in linea sulle funzioni di libreria C?

R: Usando le sezioni 2 e 3 dei manuali, rispettivamente per system calls e funzioni di libreria, ad esempio

$ man 2 read
$ man 3 printf

Come posso proteggere i miei file in modo che non siano leggibili dagli altri gruppi?

R: Basta fissare un nome di directory noto solo agli utenti del gruppo (es 56yu897j) e proteggere in lettura la directory che la contiene in modo che solo chi ne conosce il nome possa accedervi. Ad esempio

$ chmod 711 ~                    (*tolgo i diritti di lettura della mia home a tutti eccetto me*)
$ ls -ld ~
drwx--x--x    8 susanna     user          672 2005-04-12 16:48 /home/susanna/
$ mkdir ~/56yu897j               (*creo la directory segreta*)

Adesso per gli altri utenti e' impossibile fare ls sulla mia home directory es:

$ echo $USER           (* sono l'utente garibaldi*)
garibaldi
$ ls ~susanna
ls: /home/susanna/: Permission denied

Pero' posso ancora accedere alla directory 56yu897j se ne conosco il nome

$ echo $USER           (* sono l'utente garibaldi*)
garibaldi
$ ls ~susanna/56yu897j
prorub/

Ho dei Segmentation Fault quando invoco funzioni di libreria tipo free(), getenv(), etc...

R: Questo e' un tipico sintomo di errori nell'allocazione delle stringhe (spazio insufficiente), buffer overrun (come effetto spesso di strcpy() o di altre funzioni che assumono di lavorare su stringhe terminate correttamente se invocate su stringhe senza terminatore), oppure di errata gestione e copia dei puntatori.

Quindi la manifestazione spesso non ha niente a che vedere con il punto in cui si e' verificato l'errore vero e proprio.

In questo caso la cosa da fare e' ricontrollare incrementalmente tutto il codice (magari con l'aiuto di un debugger) alla ricerca di possibili malfunzionamenti su stringhe e puntatori.

Come indento il mio codice con un buon stile?

R: E' possibile usare il comando indent (vedi la sua pagina di manuale per tutte le opzioni) per indentare automaticamente il codice: una buona linea di comando e'

indent -kr -br -brs file.c

Su Vim l'indentazione puo' essere fatta tramite il comando =

Come si effettua il testing del codice?

R: Molto brevemente: il testing del codice non va confuso con il debugging (ovvero la ricerca dell'errore in un programma che si ritiene sbagliato). Infatti nel testing si cerca di mettere sotto pressione un codice in principio corretto in modo da evidenziare tempestivamente possibili malfunzionamenti.

E' buona norma testare sistematicamente i vari aspetti delle funzioni man mano che queste vengono sviluppate. In particolare e' una buona idea sviluppare, parallelamente al codice, un programma di test che stressa i punti importanti e controlla automaticamente che i risultati siano corretti.

In particolare, e' una PESSIMA idea iniziare a testare il codice dopo averne scritta gran parte. Il testing deve essere fatto incrementalmente su ogni funzione sviluppata. Questo permette di trovare piu' semplicemente gli errori perche' e' possibile concentrarsi su porzioni piu' piccole e ben definite del programma.

E' anche una buona norma raccogliere tutti i test che verificano le varie funzioni in modo da ripeterli automaticamente (con opportuni script) ogni volta che il codice viene modificato per fissare un nuovo bug o aggiungere nuove funzionalita' su una funzione gia' testata.

In rete esistono librerie che aiutano ad organizzare i test (vedi ad esempio C unit e gcov o man gcov per controllare quale parte del codice e' stata testata e quale no). Per una trattazione piu' dettagliata ma introduttiva vedi ad esempio Kerninghan & Pike capitolo 6.

Quali sono le informazioni che devono essere incluse nella relazione? Come possiamo strutturarle?

R: Una possibile struttura della relazione e' la seguente:

  1. Introduzione: deve essere una descrizione ad alto livello del progetto, rivolta ad un lettore che non sappia di cosa si tratti. Deve tracciare a grandi linee il quadro complessivo, delineando le parti giocate da quanto descritto nelle sezioni successive
    • struttura complessiva dell'implementazione
    • principali idee guida
  2. Strutture Dati: le principali strutture dati utilizzate per realizzare il progetto, si puo' fare anche un elenco puntato indicando come sono strutturate, le motivazioni della scelta, il file di header in cui sono dichiarate e quanto altro sembra opportuno
  3. Struttura del server: descrizione dettagliata della struttura del server con la descrizione delle fasi principali di elaborazione, facendo riferimento alle SD gia' descritte senza introdurle di nuovo. Ovviamente va dato piu' spazio ai punti critici rispetto a parti ovvie
  4. Struttura del client: come server
  5. Appendice
    • Guida per l'utente
      • Compilazione
      • Installazione
      • Esecuzione/terminazione del server
      • Esecuzione/Terminazione del client
      • Eventuali vincoli
  6. Problemi/bug noti (se ce ne sono :-))

Come mai la accept non funziona ?

R: Su alcune architetture la accept() va invocata con

struct sockaddr_un addr;
int ret;
socklen_t x2 = sizeof (addr);
ret = accept(s, (struct sockaddr *)&addr, &x2);

invece che passando il secondo argomento NULL.