Sophie

Sophie

distrib > Mandriva > 9.1 > i586 > by-pkgid > f1098342ec4a2b28475e34123ce17201 > files > 292

howto-html-it-9.1-0.5mdk.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>The Linux GCC HOWTO : Il porting e la compilazione</TITLE>
<LINK HREF="GCC-HOWTO-5.html" REL=next>
<LINK HREF="GCC-HOWTO-3.html" REL=previous>
<LINK HREF="GCC-HOWTO.html#toc4" REL=contents>
</HEAD>
<BODY>
<A HREF="GCC-HOWTO-5.html">Avanti</A>
<A HREF="GCC-HOWTO-3.html">Indietro</A>
<A HREF="GCC-HOWTO.html#toc4">Indice</A>
<HR>
<H2><A NAME="s4">4. Il porting e la compilazione</A></H2>

<H2><A NAME="index.25"></A> <A NAME="ss4.1">4.1 Simboli definiti automaticamente</A>
</H2>

<P>&Egrave; possibile elencare i simboli definiti automaticamente dalla propria 
versione di gcc eseguendolo con l'opzione <CODE>-v</CODE>. Ad esempio:
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ echo 'main(){printf("hello world\n");}' | gcc -E -v -
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs
gcc version 2.7.2
/usr/lib/gcc-lib/i486-box-linux/2.7.2/cpp -lang-c -v -undef
-D__GNUC__=2 -D__GNUC_MINOR__=7 -D__ELF__ -Dunix -Di386 -Dlinux
-D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__i386
-D__linux -Asystem(unix) -Asystem(posix) -Acpu(i386)
-Amachine(i386) -D__i486__ -
</PRE>
</CODE></BLOCKQUOTE>
<P>Se si sta scrivendo del codice che utilizza delle caratteristiche 
specifiche per Linux, &egrave; una buona idea includere le parti non portabili 
in 
<P>
<BLOCKQUOTE><CODE>
<PRE>
#ifdef __linux__
/* ... altro codice ... */
#endif /* linux */
</PRE>
</CODE></BLOCKQUOTE>
<P>Si utilizzi <CODE>__linux__</CODE> per questo scopo, <B>non</B> semplicemente 
<CODE>linux</CODE>. Sebbene anche il secondo sia definito, non &egrave; conforme a 
POSIX.
<P>
<H2><A NAME="ss4.2">4.2 Chiamata del compilatore</A>
</H2>

<P>La documentazione per le opzioni del compilatore &egrave; rappresentata dalla 
info page di gcc (in Emacs, si utilizzi <CODE>C-h i</CODE> quindi si 
selezioni la voce 'gcc'). Il proprio distributore potrebbe non aver 
incluso questa parte nel sistema, o la versione che si possiede potrebbe 
essere vecchia; la cosa migliore da fare in questo caso consiste nello 
scaricare l'archivio sorgente gcc da 
<A HREF="ftp://prep.ai.mit.edu/pub/gnu">ftp://prep.ai.mit.edu/pub/gnu</A> o da uno dei suoi siti mirror.
<P>La pagina di manuale gcc (<CODE>gcc.1</CODE>) di solito &egrave; obsoleta. Tentando di
leggerla si trover&agrave; questo avvertimento. 
<P>
<H3><A NAME="index.27"></A> <A NAME="index.26"></A> Opzioni del compilatore</H3>

<P>L'output di gcc pu&ograve; essere ottimizzato aggiungendo <CODE>-O</CODE><B>n</B>
alla sua riga di comando, dove <B>n</B> rappresenta un intero opzionale. I 
valori significativi di <B>n</B>, ed il loro esatto effetto, variano a 
seconda della versione; tipicamente vanno da 0 (nessuna ottimizzazione) a 
2 (molte ottimizzazioni) a 3 (moltissime ottimizzazioni). 
<P>Internamente, gcc le traduce in una serie di opzioni <CODE>-f</CODE> e <CODE>-m</CODE>. &Egrave; 
possibile vedere esattamente quale livello <CODE>-O</CODE> si lega a ogni opzione 
eseguendo <CODE>gcc -v -Q</CODE> (<CODE>Q</CODE> &egrave; un'opzione non documentata). 
Ad esempio, -O2 sul sistema dell'autore produce questo risultato:
<P>
<BLOCKQUOTE><CODE>
<PRE>
enabled:        -fdefer-pop -fcse-follow-jumps -fcse-skip-blocks
            -fexpensive-optimizations
            -fthread-jumps -fpeephole -fforce-mem -ffunction-cse -finline
            -fcaller-saves -fpcc-struct-return -frerun-cse-after-loop
            -fcommon -fgnu-linker -m80387 -mhard-float -mno-soft-float
            -mno-386 -m486 -mieee-fp -mfp-ret-in-387
</PRE>
</CODE></BLOCKQUOTE>
<P>L'utilizzo di un livello di ottimizzazione maggiore di quanto previsto 
per il proprio compilatore (ad esempio, -O6) avr&agrave; lo stesso 
risultato che utilizzare il livello pi&ugrave; alto che &egrave; in grado di supportare. 
Tuttavia, la distribuzione di codice impostato per la compilazione in 
questo modo non &egrave; una buona idea - se in versioni future saranno 
incorporate ulteriori ottimizzazioni, potrebbe accadere che interrompano 
il proprio codice. 
<P>
<A NAME="index.28"></A> <P>Gli utenti di gcc dalla versione 2.7.0 fino alla 2.7.2 dovrebbero notare 
che esiste un errore in -O2. In particolare, '<B>-fstrenght-reduction</B>' 
non funziona. &Egrave; disponibile una patch per risolvere questo problema, che
necessita della ricompilazione del gcc, altrimenti &egrave; sufficiente assicurarsi
di usare sempre l'opzione <CODE>-fno-strength-reduce</CODE>.
<P>
<H3>Opzioni specifiche per il processore</H3>

<P>Esistono altre opzioni <CODE>-m</CODE> che non sono attivate da nessun 
<CODE>-O</CODE>, e si dimostrano utili in molti casi. Le principali 
sono <CODE>-m386</CODE> e <CODE>-m486</CODE>, che indicano a gcc di favorire 
rispettivamente 386 o 486. Il codice compilato con una di queste due 
opzioni funzioner&agrave; anche su macchine dell'altro tipo; il codice 486 &egrave; pi&ugrave; 
voluminoso, ma non &egrave; pi&ugrave; lento se eseguito su 386.
<P>Attualmente non esiste un'opzione <CODE>-mpentium</CODE> o <CODE>-m586</CODE>.  Linus 
suggerisce di utilizzare 
<CODE>-m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2</CODE>, per 
ottenere l'ottimizzazione del codice 486 ma senza i salti necessari per 
l'allineamento (di cui il pentium non ha bisogno). Michael Meissner (di 
Cygnus) dice:
<P>
<BLOCKQUOTE>
La mia impressione &egrave; che <CODE>-mno-strength-reduce</CODE> produca anche un codice pi&ugrave; 
veloce sull'x86 (si noti che non mi sto riferendo all'errore relativo
all'opzione '-fstrength-reduction': altra questione). Ci&ograve; &egrave; dovuto
alla carenza di registri dell'x86 (ed il metodo di GCC di 
raggruppare i registri in registri sparsi piuttosto che in altri 
registri non aiuta molto). '<CODE>strenght-reduce</CODE>' ha come effetto l'utilizzo 
di registri addizionali per sostituire moltiplicazioni con addizioni. 
Sospetto anche che <CODE>-fcaller-saves</CODE> possa causare una perdita di
prestazioni.
</BLOCKQUOTE>

<BLOCKQUOTE>
Un'altra considerazione consiste nel fatto che <CODE>-fomit-frame-pointer</CODE> possa 
o meno rappresentare un vantaggio. Da un lato, rende disponibile un altro 
registro per l'uso; tuttavia, il modo in cui x86 codifica il suo set di 
istruzioni comporta che gli indirizzi relativi di stack occupino pi&ugrave; spazio 
rispetto agli indirizzi relativi di frame; di conseguenza, sar&agrave; 
disponibile ai programmi una quantit&agrave; (leggermente) inferiore di Icache. 
Inoltre, <CODE>-fomit-frame-pointer</CODE> implica il continuo aggiustamento del 
puntatore allo stack da parte del compilatore, dopo ogni chiamata, 
quando, con un frame, pu&ograve; lasciare che lo stack esegua un accumulo per 
alcune chiamate. 
</BLOCKQUOTE>
<P>L'ultima parola su questo argomento viene ancora da Linus:
<P>
<BLOCKQUOTE>
Se si desidera ottenere prestazioni ottimali, non credete alle mie parole,
effettuate delle prove. Esistono molte opzioni nel compilatore gcc, e pu&ograve; 
darsi che un insieme particolare dia l'ottimizzazione migliore per la 
propria impostazione.
</BLOCKQUOTE>
<P>
<H3><A NAME="index.33"></A> <A NAME="index.32"></A> <A NAME="index.31"></A> <A NAME="index.30"></A> <A NAME="index.29"></A> Internal compiler error: cc1 got fatal signal 11     </H3>

<P>(Ovvero: "Errore interno del compilatore: cc1 ha ricevuto il segnale fatale 11").
<P>Il segnale 11 &egrave; SIGSEGV, o 'segmentation violation'.  Solitamente 
significa che il programma ha confuso i puntatori e ha tentato di scrivere 
su una porzione di memoria che non possedeva. Potrebbe trattarsi di 
un errore di gcc.
<P>Tuttavia, gcc &egrave; ben verificato ed affidabile, nella maggior 
parte dei casi. Utilizza anche un gran numero di strutture dati complesse, 
e una grande quantit&agrave; di puntatori. In breve, &egrave; il miglior tester di 
RAM tra quelli disponibili comunemente. Se non &egrave; possibile replicare 
l'errore - il sistema non si ferma nello stesso punto quando si riavvia 
la compilazione - molto probabilmente si tratta di un problema legato 
all'hardware (CPU, memoria, scheda madre o cache). Non lo si deve 
considerare un errore del compilatore solo perch&eacute; il proprio computer 
supera i controlli di avvio del sistema o &egrave; in grado di eseguire Windows o 
qualunque altro programma; questi 'test' sono comunemente ritenuti, a 
ragione, di nessun valore.  Comunque &egrave; sbagliato ritenere che si tratti di 
un errore, perch&eacute; una compilazione del kernel si blocca sempre durante 
`<CODE>make zImage</CODE>' - &egrave; logico che ci&ograve; accada: `<CODE>make zImage</CODE>' 
probabilmente compila pi&ugrave; di 200 file. In genere si ricerca un 
bug in un insieme pi&ugrave; <B>piccolo</B> di cos&igrave;.
<P>Se &egrave; possibile duplicare l'errore, e (ancora meglio) produrre un breve 
programma che lo dimostra, &egrave; possibile inviarlo come report di errori 
all'FSF, o alla mailing list di <CODE>linux-gcc</CODE>. Si faccia riferimento 
alla documentazione di gcc per i dettagli relativi alle informazioni 
effettivamente necessarie.
<P>
<H2><A NAME="ss4.3">4.3 Portabilit&agrave;</A>
</H2>

<P>&Egrave; stato detto che, in questi giorni, se non pu&ograve; essere portato
a Linux, allora &egrave; qualcosa che non vale la pena di possedere. :-)
<P>In generale, sono necessarie solo piccole modifiche per ottenere la 
conformit&agrave; POSIX al 100% di Linux.  Sarebbe anche molto utile restituire 
agli autori ogni modifica al codice in modo che, in futuro, si possa
ottenere un eseguibile funzionante tramite il solo comando '<CODE>make</CODE>'. 
<P>
<H3>BSD (inclusi bsd_ioctl, demone e &lt;sgtty.h&gt;)</H3>

<P>&Egrave; possibile compilare il proprio programma con <CODE>-I/usr/include/bsd</CODE>
ed eseguire il link con <CODE>-lbsd</CODE> (ossia, aggiungere 
<CODE>-I/usr/include/bsd</CODE> a <CODE>CFLAGS</CODE> e <CODE>-lbsd</CODE> alla riga 
<CODE>LDFLAGS</CODE> nel proprio <CODE>Makefile</CODE>). Non &egrave; pi&ugrave; necessario aggiungere 
<CODE>-D__USE_BSD_SIGNAL</CODE> se si desidera un comportamento dei segnali di 
tipo BSD, dal momento che questa caratteristica viene ottenuta 
automaticamente quando si ha <CODE>-I/usr/include/bsd</CODE> e l'include 
<CODE>&lt;signal.h&gt;</CODE>.
<P>
<H3><A NAME="index.38"></A> <A NAME="index.37"></A> <A NAME="index.36"></A> <A NAME="index.35"></A> <A NAME="index.34"></A> Segnali 'mancanti' (<CODE>SIGBUS</CODE>, <CODE>SIGEMT</CODE>,<CODE>SIGIOT</CODE>, <CODE>SIGTRAP</CODE>, <CODE>SIGSYS</CODE> ecc)      </H3>

<P>Linux &egrave; conforme a POSIX. Quelli elencati nel seguito sono segnali non 
definiti in POSIX - ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), 
paragrafo B.3.3.1.1:
<P>
<BLOCKQUOTE>
"I segnali SIGBUS, SIGEMT, SIGIOT, SIGTRAP, e SIGSYS sono stati omessi da 
POSIX.1 perch&eacute; il loro comportamento dipende dall'implementazione e non &egrave; 
stato possibile classificarlo adeguatamente. Implementazioni conformi 
potranno contenere questi segnali, ma devono documentare le circostanze in cui 
sono rilasciati ed elencare ogni restrizione riguardante il loro rilascio."
</BLOCKQUOTE>
<P>Il modo pi&ugrave; economico e scadente di gestire la cosa consiste nel ridefinire 
questi segnali in <CODE>SIGUNUSED</CODE>. Il modo <B>corretto</B> consiste 
nell'inserire il codice che li gestisce in appropriati <CODE>#ifdef</CODE>
<P>
<BLOCKQUOTE><CODE>
<PRE>
#ifdef SIGSYS
/* ... codice SIGSYS non-posix .... */
#endif
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H3><A NAME="index.39"></A> Codice K &amp; R </H3>

<P>GCC &egrave; un compilatore ANSI; una grande quantit&agrave; di codice esistente non &egrave; 
ANSI. Non c'&egrave; molto da fare per risolvere questo problema, oltre 
all'aggiungere <CODE>-traditional</CODE> alle opzioni del compilatore. Si invita a 
consultare l'info page di gcc.
<P>Si noti che <CODE>-traditional</CODE> ha altri effetti oltre a cambiare il 
linguaggio accettato da gcc. Ad esempio, attiva 
<CODE>-fwritable-strings</CODE>, che sposta le stringhe costanti nello spazio 
dati (dallo spazio di codice, dove non possono essere scritte). 
Questo aumenta l'occupazione di memoria del programma. 
<P>
<H3><A NAME="index.41"></A> <A NAME="index.40"></A> Conflitto dei simboli di preprocessore con prototipi nel codice  </H3>

<P>Uno dei problemi pi&ugrave; frequenti consiste nel fatto che alcune funzioni 
comuni sono definite come macro negli header file di Linux e il 
preprocessore si rifiuter&agrave; di eseguire il parsing di definizioni 
prototipo simili. I pi&ugrave; comuni sono <CODE>atoi()</CODE> e <CODE>atol()</CODE>.
<P>
<H3><A NAME="index.42"></A> <CODE>sprintf()</CODE> </H3>

<P>Soprattutto quando si esegue il porting da SunOS, &egrave; necessario essere 
consapevoli del fatto che <CODE>sprintf(string, fmt, ...)</CODE> restituisce 
un puntatore a stringhe, mentre Linux (seguendo ANSI) restituisce il 
numero di caratteri che sono stati messi nella stringa.
<P>
<H3><A NAME="index.49"></A> <A NAME="index.48"></A> <A NAME="index.47"></A> <A NAME="index.46"></A> <A NAME="index.45"></A> <A NAME="index.44"></A> <A NAME="index.43"></A> <CODE>fcntl</CODE> e affini. Quali sono le definizioni di <CODE>FD_*</CODE>?       </H3>

<P>Le definizioni si trovano in <CODE>&lt;sys/time.h&gt;</CODE>. Se si sta 
utilizzando <CODE>fcntl</CODE>, probabilmente si vorr&agrave; includere anche 
<CODE>&lt;unistd.h&gt;</CODE>.
<P>In genere, la pagina di manuale di una funzione elenca gli 
<CODE>#include</CODE> necessarie nella sua sezione SYNOPSIS.
<P>
<H3><A NAME="index.50"></A> Il timeout di <CODE>select()</CODE>.  Programmi in busy-waiting </H3>

<P>Una volta, il parametro timeout di <CODE>select()</CODE> era utilizzato a 
sola lettura. Gi&agrave; allora, le pagine di manuale avvertivano:
<P>
<BLOCKQUOTE>
select() dovrebbe probabilmente restituire il tempo rimanente dal timeout 
originale, se esistente, modificando il valore del tempo. Questo potr&agrave; essere 
implementato in versioni future del sistema. Pertanto, sarebbe sbagliato 
ritenere che il puntatore al timeout non sar&agrave; modificato dalla chiamata 
select().
</BLOCKQUOTE>
<P>Ora il futuro &egrave; arrivato. Di ritorno da una <CODE>select()</CODE>, l'argomento 
di timeout sar&agrave; impostato al tempo rimanente che si sarebbe atteso se i 
dati non fossero arrivati. Se non &egrave; arrivato alcun dato, il valore sar&agrave; 
zero, e le chiamate future utilizzando la stessa struttura timeout 
eseguiranno immediatamente il return.
<P>Per rimediare, in caso di errore, si metta il valore di timeout nella 
struttura ogni volta che si chiama <CODE>select()</CODE>. Si modifichi il 
codice come:
<P>
<HR>
<PRE>
struct timeval timeout;
timeout.tv_sec = 1; timeout.tv_usec = 0;
while (some_condition)
        select(n,readfds,writefds,exceptfds,&amp;timeout);
</PRE>
<HR>
<P>in
<P>
<HR>
<PRE>
struct timeval timeout;
while (some_condition) {
        timeout.tv_sec = 1; timeout.tv_usec = 0;
        select(n,readfds,writefds,exceptfds,&amp;timeout);
}
</PRE>
<HR>
<P>Alcune versioni di Mosaic evidenziavano questo problema. La velocit&agrave; 
dell'animazione del globo rotante era inversamente correlata alla velocit&agrave; 
con cui i dati giungevano dalla rete!
<P>
<H3><A NAME="index.52"></A> <A NAME="index.51"></A> Chiamate di sistema interrotte  </H3>

<H3>Sintomo</H3>

<P>Quando un programma viene interrotto utilizzando <CODE>Ctrl-Z</CODE> e poi 
viene riavviato - o in altre situazioni che generano dei segnali: 
interruzione con <CODE>Ctrl-C</CODE>, terminazione di un processo figlio ecc. - 
si ottengono messaggi del tipo "interrupted system call" o "write: 
unknown error".
<P>
<H3>Problema</H3>

<P>I sistemi POSIX controllano la presenza di segnali pi&ugrave; frequentemente 
rispetto a sistemi UNIX pi&ugrave; vecchi. Linux pu&ograve; eseguire dei gestori di 
segnali:
<P>
<UL>
<LI>in modo asincrono (tramite un timer)
</LI>
<LI>al ritorno da ogni chiamata di sistema
</LI>
<LI>durante l'esecuzione delle seguenti chiamate di sistema:
<CODE>select()</CODE>, <CODE>pause()</CODE>, <CODE>connect()</CODE>, 
<CODE>accept()</CODE>, <CODE>read()</CODE> su terminali, su socket, su
pipe o su file in <CODE>/proc</CODE>, <CODE>write()</CODE> su terminali, 
su socket, su pipe o sulla line printer; <CODE>open()</CODE>
su FIFO, su PTY o su linee seriali, <CODE>ioctl()</CODE> su terminali; 
<CODE>fcntl()</CODE> con il comando <CODE>F_SETLKW</CODE>; <CODE>wait4()</CODE>, 
<CODE>syslog()</CODE>, ogni operazione TCP o NFS.</LI>
</UL>
<P>Per altri sistemi operativi potrebbe essere necessario includere in questa 
lista le chiamate di sistema <CODE>creat()</CODE>, <CODE>close()</CODE>, 
<CODE>getmsg()</CODE>, <CODE>putmsg()</CODE>, <CODE>msgrcv()</CODE>, 
<CODE>msgsnd()</CODE>, <CODE>recv()</CODE>, <CODE>send()</CODE>, <CODE>wait()</CODE>, 
<CODE>waitpid()</CODE>, <CODE>wait3()</CODE>, <CODE>tcdrain()</CODE>, 
<CODE>sigpause()</CODE>, <CODE>semop()</CODE>. 
<P>Se un segnale (per il quale il programma ha installato un gestore) avviene 
durante una chiamata di sistema, viene chiamato il gestore. Quando il 
gestore restituisce il controllo (alla chiamata di sistema), essa rileva 
che &egrave; stata interrotta e restituisce immediatamente -1 e 
<CODE>errno = EINTR</CODE>. Il programma non si aspetta che questo accada, 
pertanto si blocca. 
<P>&Egrave; possibile scegliere tra due alternative, per rimediare.
<P>
<UL>
<LI>Per ogni gestore di segnali che viene installato, aggiungere 
<CODE>SA_RESTART</CODE> ai flag <CODE>sigaction</CODE>. Per esempio, modificare 

<HR>
<PRE>
signal (sig_nr, my_signal_handler);
</PRE>
<HR>


in

<HR>
<PRE>
signal (sig_nr, my_signal_handler);
{ struct sigaction sa;
  sigaction (sig_nr, (struct sigaction *)0, &amp;sa);
#ifdef SA_RESTART
  sa.sa_flags |= SA_RESTART;
#endif
#ifdef SA_INTERRUPT
  sa.sa_flags &amp;= ~ SA_INTERRUPT;
#endif
  sigaction (sig_nr, &amp;sa, (struct sigaction *)0);
}
</PRE>
<HR>


Si noti che mentre questo viene applicato alla maggior parte delle 
chiamate di sistema, &egrave; necessario controllare <CODE>EINTR</CODE> personalmente 
riguardo a <CODE>read()</CODE>, <CODE>write()</CODE>, <CODE>ioctl()</CODE>, 
<CODE>select()</CODE>, <CODE>pause()</CODE> e <CODE>connect()</CODE> . Si veda sotto.
</LI>
<LI>Controllare <CODE>EINTR</CODE> esplicitamente.</LI>
</UL>
<P>Seguono due esempi per <CODE>read()</CODE> e <CODE>ioctl()</CODE>.
<P>Una parte di codice originale utilizzante <CODE>read()</CODE>
<P>
<HR>
<PRE>
int result;
while (len > 0) {
        result = read(fd,buffer,len);
        if (result &lt; 0) break;
        buffer += result; len -= result;
}
</PRE>
<HR>
<P>diventa
<P>
<HR>
<PRE>
int result;
while (len > 0) {
        result = read(fd,buffer,len);
        if (result &lt; 0) { if (errno != EINTR) break; }
        else { buffer += result; len -= result; }
}
</PRE>
<HR>
<P>e una parte di codice utilizzante <CODE>ioctl()</CODE>
<P>
<HR>
<PRE>
    int result;
    result = ioctl(fd,cmd,addr);
</PRE>
<HR>
<P>diventa
<P>
<HR>
<PRE>
    int result;
    do { result = ioctl(fd,cmd,addr); }
    while ((result == -1) &amp;&amp; (errno == EINTR));
</PRE>
<HR>
<P>Si noti che in alcune versioni di Unix BSD il comportamento predefinito 
consiste nel riavviare le chiamate di sistema. Per ottenere l'interruzione 
delle chiamate di sistema &egrave; necessario utilizzare i flag 
<CODE>SV_INTERRUPT</CODE> o <CODE>SA_INTERRUPT</CODE>.
<P>
<H3><A NAME="index.56"></A> <A NAME="index.55"></A> <A NAME="index.54"></A> <A NAME="index.53"></A> Stringhe scrivibili (il programma genera 'segmentation fault' in modo casuale)    </H3>

<P>GCC ha una visione ottimistica dei suoi utenti, considerando le costanti 
stringa esattamente quello che sono - delle costanti. Pertanto, le 
memorizza nell'area del codice, dove possono essere inserite ed estratte 
dall'immagine di disco del programma (invece di occupare uno
swapspace). Ne consegue che ogni tentativo di riscriverle
causer&agrave; 'segmentation fault'.
<P>Questo pu&ograve; causare dei problemi a vecchi programmi che, per esempio 
eseguono una chiamata <CODE>mktemp()</CODE> con una stringa costante come 
argomento. <CODE>mktemp()</CODE> tenta di riscrivere il suo argomento.
<P>Per correggere,
<UL>
<LI>compilare con l'opzione <CODE>-fwritable-strings</CODE>, per fare in modo 
che gcc posizioni le costanti nello spazio dati, oppure 
</LI>
<LI>riscrivere le parti che causano dei problemi per allocare una stringa 
non costante ed eseguire la <CODE>strcpy</CODE> dei dati in essa prima della 
chiamata.</LI>
</UL>
<P>
<H3><A NAME="index.57"></A> Perch&eacute; la chiamata <CODE>execl()</CODE> fallisce? </H3>

<P>Probabilmente accade perch&eacute; viene eseguita in modo errato. Il primo 
argomento per <CODE>execl</CODE> &egrave; il nome del programma da eseguire. 
Il secondo e i successivi diventano l'array <CODE>argv</CODE> del programma 
che si sta chiamando. Ricordare che: <CODE>argv[0]</CODE> viene
impostato anche per un programma eseguito senza argomenti. Pertanto si 
dovrebbe scrivere 
<P>
<HR>
<PRE>
    execl("/bin/ls","ls",NULL);
</PRE>
<HR>
<P>e non solo
<P>
<HR>
<PRE>
    execl("/bin/ls", NULL);
</PRE>
<HR>
<P>L'esecuzione del programma senza nessun argomento &egrave; interpretata come un 
invito a stampare le sue dipendenze a librerie dinamiche, almeno 
utilizzando <CODE>a.out</CODE>. ELF si comporta diversamente. 
<P>(Se si desidera questa informazione di libreria, esistono interfacce 
pi&ugrave; semplici; si veda il paragrafo relativo al caricamento dinamico, o la 
pagina di manuale per <CODE>ldd</CODE>).
<P>
<HR>
<A HREF="GCC-HOWTO-5.html">Avanti</A>
<A HREF="GCC-HOWTO-3.html">Indietro</A>
<A HREF="GCC-HOWTO.html#toc4">Indice</A>
</BODY>
</HTML>