Indice

FAQ

Ossia Frequently Asked Questions.

FRAM3 - DPLAN: si devono usare i socket AF_UNIX o AF_INET?

Nella descrizione del progetto per un errore di stampa sono nominati i socket AF_INET, tuttavia la comunicazione deve avvenire attraverso i socket AF_UNIX.

FRAM3 - DPLAN: UNIX_PATH_MAX non lo trova, che fare?

Su Linux la costante non risulta essere definita, createvi voi una macro con il valore visto a lezione nel file lcscom.h.

FRAM3 - DPLAN: E' possibile modificare i file ''.h'' forniti?

Si, basta che si tratti di “aggiunte” che non modificano i prototipi delle funzioni date.

FRAM3 - DPLAN: il server deve essere multithreaded?

Si, il server deve attivare thread paralleli per gestire le connessioni concorrenti (e' possibile attivare un thread per ogni connessione o un pool di thread). In particolare no ne' possibile usare un server con un solo thread utilizzando la select per scegliere fra i descrittori pronti.

FRAM3 - DPLAN: i test invocano le opzioni del client in ordine errato ?

NO, il client dplan (come generalmente avviene per i comandi unix) puo' essere invocato con le opzioni in ordine qualsiasi. In particolare le due versioni seguenti sono equivalenti ed accettabili

dplan -r gigi agenda.txt
dplan agenda.txt -r gigi

come anche

dplan agenda -u mario#compleanno -d 12-12-2008
dplan -u mario#compleanno -d 12-12-2008 agenda
dplan -u mario#compleanno agenda -d 12-12-2008

per evitare di impazzire, usate la funzione di libreria getopt per il parsing evitando di fare a mano tutti i casi possibili.

FRAM2 - WATOR: mangiare, spostarsi o riprodursi?

Le specifiche di Wator sono abbastanza lasche. Essenzialmente lo squalo se puo' mangia (e si sposta nella cella del pesce mangiato) altrimenti si sposta solamente. La riproduzione puo' avvenire dopo aver mangiato o essersi spostati. La scelta della preda, della cella dove spostarsi e della cella dove inserire il figlio viene effettuata casualmente sulle scelte possibili.

FRAM2 - WAKEUP: verificare la data

Per verificare il formato di data ed ora e' possibile usare direttamente il comando date con opzione -d, consultate il man relativo.

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:

FRAM1: Il grafo puo' contenere piu' archi uguali?

si`. ci possono essere grafi con archi uguali, cioe` che collegano gli stessi nodi piu` di una volta. Il primo grafo nel programma di test corrisponde al noto grafo di Eulero rappresentante i ponti della citta di koenigsberg.

FRAM1: Cosa restituisce esattamente la funzione find_clique?

La funziona find_clique restituisce il numero di clique inserite nell'array e non il numero di clique trovate in totale in quanto l'array puo' non avere spazio per tutte le clique.

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.