segue le specifiche del \textit{Filesystem Hierarchy Standard} (per maggiori
informazioni si consulti sez.~1.2.3 di \cite{AGL}) si trovano sotto
\texttt{/usr/include}.} o fra virgolette, nel qual caso si fa riferimento
-ad una versione locale, da indicare con un \itindsub{pathname}{relativo}
-\textit{pathname} relativo:
+ad una versione locale, da indicare con un \textit{pathname} relativo:
\includecodesnip{listati/main_include.c}
Si tenga presente che oltre ai nomi riservati a livello generale di cui si è
verrebbe interpretato come un successo.
Per questo motivo in \headfile{stdlib.h} sono definite, seguendo lo standard
-POSIX, le due costanti \const{EXIT\_SUCCESS} e \const{EXIT\_FAILURE}, da usare
-sempre per specificare lo stato di uscita di un processo. Su Linux, ed in
-generale in qualunque sistema POSIX, ad esse sono assegnati rispettivamente i
-valori 0 e 1.
+POSIX, le due costanti \constd{EXIT\_SUCCESS} e \constd{EXIT\_FAILURE}, da
+usare sempre per specificare lo stato di uscita di un processo. Su Linux, ed
+in generale in qualunque sistema POSIX, ad esse sono assegnati rispettivamente
+i valori 0 e 1.
\itindend{exit~status}
programma. A questo scopo lo standard ANSI C prevede la possibilità di
registrare un certo numero di funzioni che verranno eseguite all'uscita dal
programma,\footnote{nel caso di \func{atexit} lo standard POSIX.1-2001
- richiede che siano registrabili almeno \const{ATEXIT\_MAX} funzioni (il
+ richiede che siano registrabili almeno \constd{ATEXIT\_MAX} funzioni (il
valore può essere ottenuto con \func{sysconf}, vedi
sez.~\ref{sec:sys_limits}).} sia per la chiamata ad \func{exit} che per il
ritorno di \code{main}. La prima funzione che si può utilizzare a tal fine è
anche utilizzare pagine di dimensioni maggiori (di 4Mb, dette \textit{huge
page}), per sistemi con grandi quantitativi di memoria in cui l'uso di
pagine troppo piccole comporta una perdita di prestazioni. In alcuni sistemi
-la costante \const{PAGE\_SIZE}, definita in \headfile{limits.h}, indica la
+la costante \constd{PAGE\_SIZE}, definita in \headfile{limits.h}, indica la
dimensione di una pagina in byte, con Linux questo non avviene e per ottenere
questa dimensione si deve ricorrere alla funzione \func{getpagesize} (vedi
sez.~\ref{sec:sys_memory_res}).
indirizzi virtuali ai quali il processo può accedere. Solitamente un
programma C viene suddiviso nei seguenti segmenti:
\index{segmento!testo|(}
-\index{segmento!dati(}
+\index{segmento!dati|(}
\itindbeg{heap}
\itindbeg{stack}
-\begin{enumerate*}
+\begin{enumerate}
\item Il \textsl{segmento di testo} o \textit{text segment}. Contiene il
codice del programma, delle funzioni di librerie da esso utilizzate, e le
costanti. Normalmente viene condiviso fra tutti i processi che eseguono lo
globale è che essa può essere vista solo all'interno della funzione in cui
è dichiarata.} e la memoria allocata dinamicamente. Di norma è diviso in
tre parti:
- \begin{itemize*}
+ \begin{itemize}
\item Il segmento dei dati inizializzati, che contiene le variabili il cui
valore è stato assegnato esplicitamente. Ad esempio se si definisce:
\includecodesnip{listati/pi.c}
disallocare la memoria dinamica con le apposite funzioni (vedi
sez.~\ref{sec:proc_mem_alloc}), ma il suo limite inferiore, quello
adiacente al segmento dei dati non inizializzati, ha una posizione fissa.
- \end{itemize*}
+ \end{itemize}
\item Il segmento di \textit{stack}, che contiene quello che viene chiamato lo
``\textit{stack}'' del programma. Tutte le volte che si effettua una
chiamata ad una funzione è qui che viene salvato l'indirizzo di ritorno e le
La dimensione di questo segmento aumenta seguendo la crescita dello
\textit{stack} del programma, ma non viene ridotta quando quest'ultimo si
restringe.
-\end{enumerate*}
+\end{enumerate}
\begin{figure}[htb]
\centering
inizializzato a zero al caricamento del programma.
\index{segmento!testo|)}
-\index{segmento!dati)}
+\index{segmento!dati|)}
\itindend{heap}
\itindend{stack}
momento, in corrispondenza ad una qualunque chiamata di \func{malloc} che può
essere in una sezione del codice che non ha alcuna relazione con la funzione
che contiene l'errore. Per questo motivo è sempre molto difficile trovare un
-\textit{memory leak}.
-
-In C e C++ il problema è particolarmente sentito. In C++, per mezzo della
-programmazione ad oggetti, il problema dei \textit{memory leak} si può
-notevolmente ridimensionare attraverso l'uso accurato di appositi oggetti come
-gli \textit{smartpointers}. Questo però in genere va a scapito delle
-prestazioni dell'applicazione in esecuzione.
-
-% TODO decidere cosa fare di questo che segue
-% In altri linguaggi come il java e recentemente il C\# il problema non si pone
-% nemmeno perché la gestione della memoria viene fatta totalmente in maniera
-% automatica, ovvero il programmatore non deve minimamente preoccuparsi di
-% liberare la memoria allocata precedentemente quando non serve più, poiché
-% l'infrastruttura del linguaggio gestisce automaticamente la cosiddetta
-% \index{\textit{garbage~collection}} \textit{garbage collection}. In tal caso,
-% attraverso meccanismi simili a quelli del \textit{reference counting}, quando
-% una zona di memoria precedentemente allocata non è più riferita da nessuna
-% parte del codice in esecuzione, può essere deallocata automaticamente in
-% qualunque momento dall'infrastruttura.
+\textit{memory leak}. In C e C++ il problema è particolarmente sentito. In
+C++, per mezzo della programmazione ad oggetti, il problema dei \textit{memory
+ leak} si può notevolmente ridimensionare attraverso l'uso accurato di
+appositi oggetti come gli \textit{smartpointers}. Questo però in genere va a
+scapito delle prestazioni dell'applicazione in esecuzione.
+
+% TODO decidere cosa fare di questo che segue In altri linguaggi come il java
+% e recentemente il C\# il problema non si pone nemmeno perché la gestione
+% della memoria viene fatta totalmente in maniera automatica, ovvero il
+% programmatore non deve minimamente preoccuparsi di liberare la memoria
+% allocata precedentemente quando non serve più, poiché l'infrastruttura del
+% linguaggio gestisce automaticamente la cosiddetta
+% \itindex{garbage~collection} \textit{garbage collection}. In tal caso,
+% attraverso meccanismi simili a quelli del \textit{reference counting},
+% quando una zona di memoria precedentemente allocata non è più riferita da
+% nessuna parte del codice in esecuzione, può essere deallocata
+% automaticamente in qualunque momento dall'infrastruttura.
% Anche questo va a scapito delle prestazioni dell'applicazione in esecuzione
% (inoltre le applicazioni sviluppate con tali linguaggi di solito non sono
non è inserita né nello standard POSIX né in SUSv3 (ma è presente in BSD), il
suo utilizzo quindi limita la portabilità dei programmi. Inoltre la funzione
non può essere usata nella lista degli argomenti di una funzione, perché lo
-spazio verrebbe allocato nel mezzo degli stessi. Inoltre non è chiaramente
+spazio verrebbe allocato nel mezzo degli stessi. Inoltre non è chiaramente
possibile usare \func{alloca} per allocare memoria che deve poi essere usata
anche al di fuori della funzione in cui essa viene chiamata, dato che
all'uscita dalla funzione lo spazio allocato diventerebbe libero, e potrebbe
\textit{segment violation} la prima volta che cercherà di accedere alla
memoria non effettivamente disponibile.
-
\index{segmento!dati|(}
\itindbeg{heap}
La funzione è un'interfaccia all'omonima \textit{system call} ed imposta
l'indirizzo finale del segmento dati di un processo (più precisamente dello
\textit{heap}) all'indirizzo specificato da \param{addr}. Quest'ultimo deve
-essere un valore ragionevole, e la dimensione totale non deve comunque
-eccedere un eventuale limite (vedi sez.~\ref{sec:sys_resource_limit}) imposto
-sulle dimensioni massime del segmento dati del processo.
+essere un valore ragionevole e la dimensione totale non deve comunque eccedere
+un eventuale limite (vedi sez.~\ref{sec:sys_resource_limit}) sulle dimensioni
+massime del segmento dati del processo.
Il valore di ritorno della funzione fa riferimento alla versione fornita dalla
\acr{glibc}, in realtà in Linux la \textit{system call} corrispondente
Il sistema pone dei limiti all'ammontare di memoria di un processo che può
essere bloccata e al totale di memoria fisica che si può dedicare a questo, lo
standard POSIX.1 richiede che sia definita in \headfile{unistd.h} la macro
-\macro{\_POSIX\_MEMLOCK\_RANGE} per indicare la capacità di eseguire il
+\macrod{\_POSIX\_MEMLOCK\_RANGE} per indicare la capacità di eseguire il
\textit{memory locking}.
Siccome la richiesta di un \textit{memory lock} da parte di un processo riduce
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \const{MCL\_CURRENT}& blocca tutte le pagine correntemente mappate nello
- spazio di indirizzi del processo.\\
- \const{MCL\_FUTURE} & blocca tutte le pagine che verranno mappate nello
- spazio di indirizzi del processo.\\
+ \constd{MCL\_CURRENT}& blocca tutte le pagine correntemente mappate nello
+ spazio di indirizzi del processo.\\
+ \constd{MCL\_FUTURE} & blocca tutte le pagine che verranno mappate nello
+ spazio di indirizzi del processo.\\
\hline
\end{tabular}
\caption{Valori e significato dell'argomento \param{flags} della funzione
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \const{MCHECK\_OK} & Riportato a \func{mprobe} se nessuna
- inconsistenza è presente.\\
- \const{MCHECK\_DISABLED}& Riportato a \func{mprobe} se si è chiamata
- \func{mcheck} dopo aver già usato
- \func{malloc}.\\
- \const{MCHECK\_HEAD} & I dati immediatamente precedenti il buffer sono
- stati modificati, avviene in genere quando si
- decrementa eccessivamente il valore di un
- puntatore scrivendo poi prima dell'inizio del
- buffer.\\
- \const{MCHECK\_TAIL} & I dati immediatamente seguenti il buffer sono
- stati modificati, succede quando si va scrivere
- oltre la dimensione corretta del buffer.\\
- \const{MCHECK\_FREE} & Il buffer è già stato disallocato.\\
+ \constd{MCHECK\_OK} & Riportato a \func{mprobe} se nessuna
+ inconsistenza è presente.\\
+ \constd{MCHECK\_DISABLED}& Riportato a \func{mprobe} se si è chiamata
+ \func{mcheck} dopo aver già usato
+ \func{malloc}.\\
+ \constd{MCHECK\_HEAD} & I dati immediatamente precedenti il buffer sono
+ stati modificati, avviene in genere quando si
+ decrementa eccessivamente il valore di un
+ puntatore scrivendo poi prima dell'inizio del
+ buffer.\\
+ \constd{MCHECK\_TAIL} & I dati immediatamente seguenti il buffer sono
+ stati modificati, succede quando si va scrivere
+ oltre la dimensione corretta del buffer.\\
+ \constd{MCHECK\_FREE} & Il buffer è già stato disallocato.\\
\hline
\end{tabular}
\caption{Valori dello stato dell'allocazione di memoria ottenibili dalla
opzioni sono spostati in coda al vettore. Oltre a questa esistono altre due
modalità di gestire gli elementi di \param{argv}; se \param{optstring} inizia
con il carattere ``\texttt{+}'' (o è impostata la variabile di ambiente
-\macro{POSIXLY\_CORRECT}) la scansione viene fermata non appena si incontra un
+\cmd{POSIXLY\_CORRECT}) la scansione viene fermata non appena si incontra un
elemento che non è un'opzione.
L'ultima modalità, usata quando un programma può gestire la mescolanza fra
\subsection{Il passaggio di un numero variabile di argomenti}
\label{sec:proc_variadic}
-\index{funzioni!variadic|(}
+\index{funzioni!\textit{variadic}|(}
Come vedremo nei capitoli successivi, non sempre è possibile specificare un
numero fisso di argomenti per una funzione. Lo standard ISO C prevede nella
pertanto quella sequenziale, in cui vengono estratti dallo \textit{stack}
secondo l'ordine in cui sono stati scritti nel prototipo della funzione.
+\macrobeg{va\_start}
+
Per fare questo in \headfile{stdarg.h} sono definite delle macro specifiche,
previste dallo standard ISO C89, che consentono di eseguire questa operazione.
La prima di queste macro è \macro{va\_start}, che inizializza opportunamente
parametro \param{last} deve indicare il nome dell'ultimo degli argomenti fissi
dichiarati nel prototipo della funzione \textit{variadic}.
+\macrobeg{va\_arg}
+
La seconda macro di gestione delle liste di argomenti di una funzione
\textit{variadic} è \macro{va\_arg}, che restituisce in successione un
argomento della lista; la sua definizione è:
risultati indefiniti anche quando si chiama \macro{va\_arg} specificando un
tipo che non corrisponde a quello usato per il corrispondente argomento.
+\macrobeg{va\_end}
+
Infine una volta completata l'estrazione occorre indicare che si sono concluse
-le operazioni con la macro \macro{va\_end}, la cui definizione è:
+le operazioni con la macro \macrod{va\_end}, la cui definizione è:
{\centering
\begin{funcbox}{
(anche se non si era completata l'estrazione) dato che il valore di \param{ap}
risulterebbe indefinito.
+\macroend{va\_start}
+\macroend{va\_arg}
+\macroend{va\_end}
+
Esistono dei casi in cui è necessario eseguire più volte la scansione degli
argomenti e poter memorizzare una posizione durante la stessa. In questo caso
sembrerebbe naturale copiarsi la lista degli argomenti \param{ap} con una
Per questo motivo una variabile di tipo \type{va\_list} non può essere
assegnata direttamente ad un'altra variabile dello stesso tipo, ma lo standard
ISO C99\footnote{alcuni sistemi che non hanno questa macro provvedono al suo
- posto \macro{\_\_va\_copy} che era il nome proposto in una bozza dello
+ posto \macrod{\_\_va\_copy} che era il nome proposto in una bozza dello
standard.} ha previsto una macro ulteriore che permette di eseguire la
copia di una lista degli argomenti:
La macro copia l'attuale della lista degli argomenti \param{src} su una nuova
lista \param{dest}. Anche in questo caso è buona norma chiudere ogni
-esecuzione di una \macro{va\_copy} con una corrispondente \macro{va\_end} sul
+esecuzione di una \macrod{va\_copy} con una corrispondente \macro{va\_end} sul
nuovo puntatore alla lista degli argomenti.
La chiamata di una funzione con un numero variabile di argomenti, posto che la
usa un puntatore \val{NULL} per indicare la fine della lista degli argomenti
(vedi sez.~\ref{sec:proc_exec}).
-\index{funzioni!variadic|)}
+\index{funzioni!\textit{variadic}|)}
\subsection{Il controllo di flusso non locale}
\label{sec:proc_longjmp}
specificato 0 sarà comunque restituito 1 al suo posto.
In sostanza l'esecuzione di \func{longjmp} è analoga a quella di una
-istruzione \instruction{return}, solo che invece di ritornare alla riga
+istruzione \instr{return}, solo che invece di ritornare alla riga
successiva della funzione chiamante, il programma in questo caso ritorna alla
posizione della relativa \func{setjmp}. L'altra differenza fondamentale con
-\instruction{return} è che il ritorno può essere effettuato anche attraverso
+\instr{return} è che il ritorno può essere effettuato anche attraverso
diversi livelli di funzioni annidate.
L'implementazione di queste funzioni comporta alcune restrizioni dato che esse
In generale, dato che l'unica differenza fra la chiamata diretta e quella
ottenuta nell'uscita con un \func{longjmp} è costituita dal valore di ritorno
di \func{setjmp}, pertanto quest'ultima viene usualmente chiamata all'interno
-di un una istruzione \instruction{if} che permetta di distinguere i due casi.
+di un una istruzione \instr{if} che permetta di distinguere i due casi.
Uno dei punti critici dei salti non-locali è quello del valore delle
variabili, ed in particolare quello delle variabili automatiche della funzione
a cui si ritorna. In generale le variabili globali e statiche mantengono i
valori che avevano al momento della chiamata di \func{longjmp}, ma quelli
-delle variabili automatiche (o di quelle dichiarate \direct{register}) sono in
+delle variabili automatiche (o di quelle dichiarate \dirct{register}) sono in
genere indeterminati.
Quello che succede infatti è che i valori delle variabili che sono tenute in