Il sistema fa partire qualunque programma chiamando la funzione \func{main};
sta al programmatore chiamare così la funzione principale del programma da cui
si suppone iniziare l'esecuzione; in ogni caso senza questa funzione lo stesso
-\textit{linker} darebbe luogo ad errori.
-
-Lo standard ISO C specifica che la funzione \func{main} può non avere
-argomenti o prendere due argomenti che rappresentano gli argomenti passati da
-linea di comando, in sostanza un prototipo che va sempre bene è il seguente:
+\textit{linker} (ci chiama così il programma che effettua i collegamenti di
+cui sopra) darebbe luogo ad errori. Lo standard ISO C specifica che la
+funzione \func{main} può non avere argomenti o prendere due argomenti che
+rappresentano gli argomenti passati da linea di comando, in sostanza un
+prototipo che va sempre bene è il seguente:
\includecodesnip{listati/main_def.c}
In realtà nei sistemi Unix esiste un'altro modo per definire la funzione
\func{main}, che prevede la presenza di un terzo argomento, \code{char
- *envp[]}, che fornisce l'\textsl{ambiente} (vedi sez.~\ref{sec:proc_environ})
-del programma; questa forma però non è prevista dallo standard POSIX.1 per cui
-se si vogliono scrivere programmi portabili è meglio evitarla.
+ *envp[]}, che fornisce (vedi sez.~\ref{sec:proc_environ})
+l'\textsl{ambiente} del programma; questa forma però non è prevista dallo
+standard POSIX.1 per cui se si vogliono scrivere programmi portabili è meglio
+evitarla.
\subsection{Come chiudere un programma}
La funzione chiude tutti i file descriptor appartenenti al processo (si tenga
presente che questo non comporta il salvataggio dei dati bufferizzati degli
-stream), fa sì che ogni figlio del processo sia ereditato da \cmd{init} (vedi
+stream), fa sì che ogni figlio del processo sia adottato da \cmd{init} (vedi
cap.~\ref{cha:process_handling}), manda un segnale \const{SIGCHLD} al processo
padre (vedi sez.~\ref{sec:sig_job_control}) ed infine ritorna lo stato di
uscita specificato in \param{status} che può essere raccolto usando la
in cui gli indirizzi vanno da zero ad un qualche valore massimo.\footnote{nel
caso di Linux fino al kernel 2.2 detto massimo era, per macchine a 32bit, di
2Gb. Con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite
- è stato esteso.}
+ è stato esteso anche per macchine a 32 bit.}
Come accennato in cap.~\ref{cha:intro_unix} questo spazio di indirizzi è
virtuale e non corrisponde all'effettiva posizione dei dati nella RAM del
puntatori a \val{NULL}).\footnote{si ricordi che questo vale solo per le
variabili che vanno nel segmento dati, e non è affatto vero in generale.}
- Storicamente questo segmento viene chiamato BSS (da \textit{block started by
- symbol}). La sua dimensione è fissa.
+ Storicamente questa seconda parte del segmento dati viene chiamata BSS (da
+ \textit{Block Started by Symbol}). La sua dimensione è fissa.
\item Lo \textit{heap}. Tecnicamente lo si può considerare l'estensione del
segmento dati, a cui di solito è posto giusto di seguito. È qui che avviene
\begin{figure}[htb]
\centering
- \includegraphics[height=12cm]{img/memory_layout}
+ \includegraphics[height=11cm]{img/memory_layout}
\caption{Disposizione tipica dei segmenti di memoria di un processo.}
\label{fig:proc_mem_layout}
\end{figure}
per queste variabili viene allocato nello stack quando viene eseguita la
funzione e liberato quando si esce dalla medesima.
-Esiste però un terzo tipo di allocazione, l'\textsl{allocazione dinamica della
- memoria}, che non è prevista direttamente all'interno del linguaggio C, ma
-che è necessaria quando il quantitativo di memoria che serve è determinabile
-solo durante il corso dell'esecuzione del programma.
+Esiste però un terzo tipo di allocazione, l'\textsl{allocazione dinamica}
+della memoria, che non è prevista direttamente all'interno del linguaggio C,
+ma che è necessaria quando il quantitativo di memoria che serve è
+determinabile solo durante il corso dell'esecuzione del programma.
Il C non consente di usare variabili allocate dinamicamente, non è possibile
cioè definire in fase di programmazione una variabile le cui dimensioni
specializzata per il debugging). Esistono varie librerie che forniscono dei
sostituti opportuni delle routine di allocazione in grado, senza neanche
ricompilare il programma,\footnote{esempi sono \textit{Dmalloc}
- \href{http://dmalloc.com/}{http://dmalloc.com/} di Gray Watson ed
+ \href{http://dmalloc.com/}{\textsf{http://dmalloc.com/}} di Gray Watson ed
\textit{Electric Fence} di Bruce Perens.} di eseguire diagnostiche anche
molto complesse riguardo l'allocazione della memoria.
-
-\subsection{La funzione \func{alloca}}
-\label{sec:proc_mem_alloca}
+\subsection{Le funzioni \func{alloca}, \func{brk} e \func{sbrk}}
+\label{sec:proc_mem_sbrk_alloca}
Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
problemi di \textit{memory leak}\index{\textit{memory~leak}} descritti in
cui torneremo in sez.~\ref{sec:proc_auto_var}.
-\subsection{Le funzioni \func{brk} e \func{sbrk}}
-\label{sec:proc_mem_sbrk}
-
Queste due funzioni vengono utilizzate soltanto quando è necessario effettuare
direttamente la gestione della memoria associata allo spazio dati di un
processo, ad esempio qualora si debba implementare la propria versione delle
\begin{figure}[htb]
\centering
- \includegraphics[width=11cm]{img/argv_argc}
+ \includegraphics[width=13cm]{img/argv_argc}
\caption{Esempio dei valori di \param{argv} e \param{argc} generati nella
scansione di una riga di comando.}
\label{fig:proc_argv_argc}
In generale un programma Unix riceve da linea di comando sia gli argomenti che
le opzioni, queste ultime sono standardizzate per essere riconosciute come
tali: un elemento di \param{argv} che inizia con il carattere \texttt{'-'} e
-che non sia un singolo \texttt{'-'} o un \texttt{'--'} viene considerato
+che non sia un singolo \texttt{'-'} o un \texttt{'-{}-'} viene considerato
un'opzione. In genere le opzioni sono costituite da una lettera singola
(preceduta dal carattere \cmd{'-'}) e possono avere o no un parametro
associato; un comando tipico può essere quello mostrato in
dichiarata in \param{optstring} viene ritornato il carattere \texttt{'?'}
mentre se un opzione che lo richiede non è seguita da un parametro viene
ritornato il carattere \texttt{':'}, infine se viene incontrato il valore
-\texttt{'--'} la scansione viene considerata conclusa, anche se vi sono altri
+\texttt{'-{}-'} la scansione viene considerata conclusa, anche se vi sono altri
elementi di \param{argv} che cominciano con il carattere \texttt{'-'}.
\begin{figure}[htb]
fig.~\ref{fig:proc_envirno_list}.
\begin{figure}[htb]
\centering
- \includegraphics[width=11cm]{img/environ_var}
+ \includegraphics[width=13cm]{img/environ_var}
\caption{Esempio di lista delle variabili di ambiente.}
\label{fig:proc_envirno_list}
\end{figure}
numero fisso di argomenti per una funzione. Lo standard ISO C prevede nella
sua sintassi la possibilità di definire delle \textit{variadic
function}\index{variadic} che abbiano un numero variabile di argomenti,
-attraverso l'uso della \textit{ellipsis} \code{...} nella dichiarazione della
-funzione; ma non provvede a livello di linguaggio alcun meccanismo con cui
-dette funzioni possono accedere ai loro argomenti.
-
-L'accesso viene invece realizzato dalle librerie standard che provvedono gli
-strumenti adeguati. L'uso delle \textit{variadic function} prevede tre punti:
-\begin{itemize*}
+attraverso l'uso nella dichiarazione della funzione dello speciale costrutto
+``\texttt{...}'', che viene chiamato \textit{ellipsis}.
+
+Lo standard però non provvede a livello di linguaggio alcun meccanismo con cui
+dette funzioni possono accedere ai loro argomenti. L'accesso viene pertanto
+realizzato a livello delle librerie standard del C che provvedono gli
+strumenti adeguati. L'uso di una \textit{variadic function} prevede quindi
+tre punti:
+\begin{itemize}
\item \textsl{Dichiarare} la funzione come \textit{variadic} usando un
prototipo che contenga una \textit{ellipsis}.
-\item \textsl{Definire} la funzione come \textit{variadic} usando lo stesso
+\item \textsl{Definire} la funzione come \textit{variadic} usando la stessa
\textit{ellipsis}, ed utilizzare le apposite macro che consentono la
gestione di un numero variabile di argomenti.
-\item \textsl{Chiamare} la funzione specificando prima gli argomenti fissi, e
- a seguire gli addizionali.
-\end{itemize*}
+\item \textsl{Invocare} la funzione specificando prima gli argomenti fissi, ed
+ a seguire quelli addizionali.
+\end{itemize}
Lo standard ISO C prevede che una \textit{variadic function}\index{variadic}
abbia sempre almeno un argomento fisso; prima di effettuare la dichiarazione
sequenziale; essi verranno estratti dallo stack secondo l'ordine in cui sono
stati scritti. Per fare questo in \file{stdarg.h} sono definite delle apposite
macro; la procedura da seguire è la seguente:
-\begin{enumerate*}
+\begin{enumerate}
\item Inizializzare un puntatore alla lista degli argomenti di tipo
\macro{va\_list} attraverso la macro \macro{va\_start}.
\item Accedere ai vari argomenti opzionali con chiamate successive alla macro
il secondo e così via.
\item Dichiarare la conclusione dell'estrazione degli argomenti invocando la
macro \macro{va\_end}.
-\end{enumerate*}
+\end{enumerate}
in generale è perfettamente legittimo richiedere meno argomenti di quelli che
potrebbero essere stati effettivamente forniti, e nella esecuzione delle
\macro{va\_arg} ci si può fermare in qualunque momento ed i restanti argomenti
\index{salto~non-locale|(}
-Il C però non consente di effettuare un salto ad
-una etichetta definita in un'altra funzione, per cui se l'errore avviene in
-una funzione, e la sua gestione ordinaria è in un'altra, occorre usare quello
-che viene chiamato un \textsl{salto non-locale}. Il caso classico in cui si
-ha questa necessità, citato sia da \cite{APUE} che da \cite{glibc}, è quello
-di un programma nel cui corpo principale vengono letti dei dati in ingresso
-sui quali viene eseguita, tramite una serie di funzioni di analisi, una
-scansione dei contenuti da si ottengono le indicazioni per l'esecuzione delle
-opportune operazioni.
+Il C però non consente di effettuare un salto ad una etichetta definita in
+un'altra funzione, per cui se l'errore avviene in una funzione, e la sua
+gestione ordinaria è in un'altra, occorre usare quello che viene chiamato un
+\textsl{salto non-locale}. Il caso classico in cui si ha questa necessità,
+citato sia in \cite{APUE} che in \cite{glibc}, è quello di un programma nel
+cui corpo principale vengono letti dei dati in ingresso sui quali viene
+eseguita, tramite una serie di funzioni di analisi, una scansione dei
+contenuti, da cui si ottengono le indicazioni per l'esecuzione di opportune
+operazioni.
Dato che l'analisi può risultare molto complessa, ed opportunamente suddivisa
in fasi diverse, la rilevazione di un errore nei dati in ingresso può accadere
chiamate a questa funzione sono sicure solo in uno dei seguenti casi:
\begin{itemize}
\item come espressione di controllo in un comando condizionale, di selezione
- o di iterazione (come \code{if}, \code{switch} o \code{while}).
+ o di iterazione (come \code{if}, \code{switch} o \code{while});
\item come operando per un operatore di uguaglianza o confronto in una
espressione di controllo di un comando condizionale, di selezione o di
- iterazione.
+ iterazione;
\item come operando per l'operatore di negazione (\code{!}) in una espressione
di controllo di un comando condizionale, di selezione o di iterazione.
\item come espressione a sé stante.