<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <TITLE>The Linux GCC HOWTO : Debugging e Profiling</TITLE> <LINK HREF="GCC-HOWTO-6.html" REL=next> <LINK HREF="GCC-HOWTO-4.html" REL=previous> <LINK HREF="GCC-HOWTO.html#toc5" REL=contents> </HEAD> <BODY> <A HREF="GCC-HOWTO-6.html">Avanti</A> <A HREF="GCC-HOWTO-4.html">Indietro</A> <A HREF="GCC-HOWTO.html#toc5">Indice</A> <HR> <H2><A NAME="s5">5. Debugging e Profiling</A></H2> <H2><A NAME="index.58"></A> <A NAME="ss5.1">5.1 Manutenzione preventiva (lint)</A> </H2> <P>Non esiste un <CODE>lint</CODE> ampiamente utilizzato per Linux, dal momento che la maggior parte della gente si accontenta degli avvertimenti che gcc può generare. Probabilmente, quello più utile è il <CODE>-Wall</CODE> opzione che significa 'Warnings, all' ma probabilmente ha un maggior valore mnemonico, se pensato come qualcosa contro cui si sbatte la testa (NdT. "wall" in inglese significa "muro"). <P>Esiste un lint di dominio pubblico disponibile su <A HREF="ftp://larch.lcs.mit.edu/pub/Larch/lclint">ftp://larch.lcs.mit.edu/pub/Larch/lclint</A>. Putroppo non sono in grado di giudicare la sua validità. <P> <H2><A NAME="index.59"></A> <A NAME="ss5.2">5.2 Debugging</A> </H2> <H3><A NAME="index.62"></A> <A NAME="index.61"></A> <A NAME="index.60"></A> Come si ottengono le informazioni di debug in un programma? </H3> <P>È necessario compilare ed eseguire il link di tutte le sue parti con l'opzione <CODE>-g</CODE>, e senza <CODE>-fomit-frame-pointer</CODE>. Non è necessario ricompilarlo interamente, solo le parti di cui si esegue il debug. <P>Nelle configurazioni a.out le librerie condivise sono compilate con <CODE>-fomit-frame-pointer</CODE>, con la quale gdb non funzionerà. Questo perché l'opzione <CODE>-g</CODE> implica un link statico. <P>Se il linker va in errore fornendo un messaggio che indica l'impossibilità di trovare <CODE>libg.a</CODE>, significa che non si possiede <CODE>/usr/lib/libg.a</CODE>, che consiste nella speciale libreria C abilitata al debugging. Tale libreria può essere fornita nel pacchetto binario libc, oppure (in versioni di libreria C più recenti) può essere necessario ottenere il codice sorgente libc ed eseguire personalmente la compilazione. Tuttavia, è possibile ottenere sufficienti informazioni per la maggior parte degli scopi semplicemente sostituendola con un collegamento simbolico con <CODE>/usr/lib/libc.a</CODE>. <P> <H3><A NAME="index.63"></A> Come eliminarle? </H3> <P>Molto software GNU è impostato affinché la compilazione e il link siano eseguite con l'opzione <CODE>-g</CODE>, che determina la generazione di eseguibili molto voluminosi (e spesso statici). Questa non è una buona idea. <P>Se il programma possiede uno script di configurazione `<CODE>autoconf</CODE>', è possibile disabilitare le informazioni di debugging controllando il <CODE>Makefile</CODE>. Naturalmente, se si sta utilizzando ELF, il link del programma viene eseguito in modo dinamico indipendentemente dall'impostazione <CODE>-g</CODE>, pertanto si può semplicemente usare <CODE>strip</CODE>. <P> <H3><A NAME="index.64"></A> Software disponibile </H3> <P>Molte persone utilizzano gdb, che può essere ottenuto in forma sorgente dai siti di archivio GNU <A HREF="ftp://prep.ai.mit.edu/pub/gnu">ftp://prep.ai.mit.edu/pub/gnu</A>, oppure in formato binario da <A HREF="ftp://tsx-11.mit.edu/pub/linux/packages/GCC">tsx-11 (ftp://tsx-11.mit.edu/pub/linux/packages/GCC)</A> o da sunsite. <CODE>xxgdb</CODE> è un debugger X basato su gdb (ossia, è necessario che sia installato gdb). È possibile trovare i sorgenti presso <A HREF="ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz">ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz</A>. <P>Rick Sladkey ha eseguito il porting del debugger UPS. Può essere eseguito anche sotto X, ma a differenza di <CODE>xxgdb</CODE>, non è un semplice front end X per un debugger basato su testo. Possiede diverse caratteristiche molto interessanti, e se si ha la necessità di eseguire diversi debug, è il caso di provarlo. La versione precompilata per Linux e i patch per i sorgenti UPS possono essere trovati in <A HREF="ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/">ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/</A>, mentre i sorgenti originali in <A HREF="ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z">ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z</A>. <P>Un altro strumento utile per il debug è '<CODE>strace</CODE>', che visualizza le chiamate di sistema fatte da un processo. Questo strumento possiede anche molti altri utilizzi, inclusa la possibilità di sapere i nomi di file compilati, di cui non si possiede il sorgente; di esasperare i race condition in programmi che si sospettano contenerle, e in generale di imparare come funzionano le cose. La versione più recente di <CODE>strace</CODE> (attualmente la 3.0.8) può essere trovata in <A HREF="ftp://ftp.std.com/pub/jrs/">ftp://ftp.std.com/pub/jrs/</A>. <P> <H3>Programmi background (demone)</H3> <P>I programmi demone tipicamente eseguono presto la <CODE>fork()</CODE>, e terminano il programma chiamante. Questo rende la sessione di debug molto breve. <P>Il modo più semplice per aggirare questo ostacolo consiste nell'impostare un breakpoint per <CODE>fork</CODE>, e quando il programma si blocca, forzare la restituzione di 0. <P> <BLOCKQUOTE><CODE> <PRE> (gdb) list 1 #include <stdio.h> 2 3 main() 4 { 5 if(fork()==0) printf("child\n"); 6 else printf("parent\n"); 7 } (gdb) break fork Breakpoint 1 at 0x80003b8 (gdb) run Starting program: /home/dan/src/hello/./fork Breakpoint 1 at 0x400177c4 Breakpoint 1, 0x400177c4 in fork () (gdb) return 0 Make selected stack frame return now? (y or n) y #0 0x80004a8 in main () at fork.c:5 5 if(fork()==0) printf("child\n"); (gdb) next Step singolo fino all'uscita dalla funzione fork, che non contiene informazioni sul numero di riga. child 7 } </PRE> </CODE></BLOCKQUOTE> <P> <H3>Core file</H3> <P>Quando Linux viene avviato, solitamente è configurato per non produrre core file. Se si desidera, è possibile utilizzare il comando interno dell'interprete comandi per riabilitarli: per <I>shell</I> compatibili C (come <CODE>tcsh</CODE>) corrisponde al comando <P> <BLOCKQUOTE><CODE> <PRE> % limit core unlimited </PRE> </CODE></BLOCKQUOTE> <P>mentre per interpreti comandi di tipo Bourne (<CODE>sh</CODE>, <CODE>bash</CODE>, <CODE>zsh</CODE>, <CODE>pdksh</CODE>) utilizzare <P> <BLOCKQUOTE><CODE> <PRE> $ ulimit -c unlimited </PRE> </CODE></BLOCKQUOTE> <P>Se si desidera una maggiore flessibilità nell'assegnazione dei nomi ai core file (nel caso, per esempio, di analisi post-mortem con un debugger che contiene errori) è possibile eseguire una piccola modifica al proprio kernel. Cercare in <CODE>fs/binfmt_aout.c</CODE> e <CODE>fs/binfmt_elf.c</CODE> il codice tipo: <P> <HR> <PRE> memcpy(corefile,"core.",5); #if 0 memcpy(corefile+5,current->comm,sizeof(current->comm)); #else corefile[4] = '\0'; #endif </PRE> <HR> <P>e modificare gli <CODE>0</CODE> in <CODE>1</CODE>. <P> <H2><A NAME="ss5.3">5.3 Profiling</A> </H2> <P>Il profiling rappresenta un modo per esaminare le parti di un programma richiamate più frequentemente o eseguite più a lungo. È buona norma ottimizzare il codice e vedere dove viene perso del tempo. È necessario compilare tutti i file oggetto sui quali si desiderano informazioni sul tempo di esecuzione con l'opzione <CODE>-p</CODE>, e per interpretare il file di output sarà necessario anche <CODE>gprof</CODE> (dal pacchetto binutils). Si veda la pagina di manuale <CODE>gprof</CODE> per ulteriori dettagli. <P> <HR> <A HREF="GCC-HOWTO-6.html">Avanti</A> <A HREF="GCC-HOWTO-4.html">Indietro</A> <A HREF="GCC-HOWTO.html#toc5">Indice</A> </BODY> </HTML>