+%% process.tex
+%%
+%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
\chapter{L'interfaccia base con i processi}
\label{cha:process_interface}
\end{lstlisting}
questo vettore sarà immagazzinato in questo segmento. Anch'esso viene
allocato all'avvio, e tutte le variabili vengono inizializzate a zero (ed i
- puntatori a \macro{NULL}).\footnote{si ricordi che questo vale solo per le
+ 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 BBS (da \textit{block started by
Alloca \var{size} byte nello heap. La memoria viene inizializzata a 0.
La funzione restituisce il puntatore alla zona di memoria allocata in caso
- di successo e \macro{NULL} in caso di fallimento, nel qual caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
\var{errno} assumerà il valore \macro{ENOMEM}.
\funcdecl{void *malloc(size\_t size)}
Alloca \var{size} byte nello heap. La memoria non viene inizializzata.
La funzione restituisce il puntatore alla zona di memoria allocata in caso
- di successo e \macro{NULL} in caso di fallimento, nel qual caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
\var{errno} assumerà il valore \macro{ENOMEM}.
\funcdecl{void *realloc(void *ptr, size\_t size)}
Cambia la dimensione del blocco allocato all'indirizzo \var{ptr}
portandola a \var{size}.
La funzione restituisce il puntatore alla zona di memoria allocata in caso
- di successo e \macro{NULL} in caso di fallimento, nel qual caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
\var{errno} assumerà il valore \macro{ENOMEM}.
\funcdecl{void free(void *ptr)}
Disalloca lo spazio di memoria puntato da \var{ptr}.
multipli di 8 byte.
In genere si usano le funzioni \func{malloc} e \func{calloc} per allocare
-dinamicamente la memoria necessaria al programma, e siccome i puntatori
-ritornati sono di tipo generico non è necessario effettuare un cast per
-assegnarli a puntatori al tipo di variabile per la quale si effettua
-l'allocazione.
+dinamicamente la quantità di memoria necessaria al programma indicata da
+\param{size},\footnote{queste funzioni presentano un comportamento diverso fra
+ le \acr{glibc} e le \acr{uClib} quando il valore di \param{size} è nullo.
+ Nel primo caso viene comunque restituito un puntatore valido, anche se non è
+ chiaro a cosa esso possa fare riferimento, nel secondo caso viene restituito
+ \val{NULL}. Il comportamento è analogo con \code{realloc(NULL, 0)}.} e
+siccome i puntatori ritornati sono di tipo generico non è necessario
+effettuare un cast per assegnarli a puntatori al tipo di variabile per la
+quale si effettua l'allocazione.
La memoria allocata dinamicamente deve essere esplicitamente rilasciata usando
\func{free}\footnote{le glibc provvedono anche una funzione \func{cfree}
La funzione \func{realloc} si usa invece per cambiare (in genere aumentare) la
dimensione di un'area di memoria precedentemente allocata, la funzione vuole
in ingresso il puntatore restituito dalla precedente chiamata ad una
-\func{malloc} (se è passato un valore \macro{NULL} allora la funzione si
+\func{malloc} (se è passato un valore \val{NULL} allora la funzione si
comporta come \func{malloc})\footnote{questo è vero per Linux e
l'implementazione secondo lo standard ANSI C, ma non è vero per alcune
vecchie implementazioni, inoltre alcune versioni delle librerie del C
Un errore abbastanza frequente (specie se si ha a che fare con array di
puntatori) è quello di chiamare \func{free} più di una volta sullo stesso
puntatore; per evitare questo problema una soluzione di ripiego è quella di
-assegnare sempre a \macro{NULL} ogni puntatore liberato con \func{free}, dato
+assegnare sempre a \val{NULL} ogni puntatore liberato con \func{free}, dato
che, quando il parametro è un puntatore nullo, \func{free} non esegue nessuna
operazione.
versione meno efficiente delle funzioni suddette, che però è più tollerante
nei confronti di piccoli errori come quello di chiamate doppie a \func{free}.
In particolare:
-\begin{itemize*}
+\begin{itemize}
\item se la variabile è posta a zero gli errori vengono ignorati.
\item se è posta ad 1 viene stampato un avviso sullo \textit{standard error}
(vedi \secref{sec:file_std_stream}).
\item se è posta a 2 viene chiamata \func{abort}, che in genere causa
l'immediata conclusione del programma.
-\end{itemize*}
+\end{itemize}
Il problema più comune e più difficile da risolvere che si incontra con le
routine di allocazione è quando non viene opportunamente liberata la memoria
non più utilizzata, quello che in inglese viene chiamato \textit{memory-leak},
-cioè \textsl{perdita di memoria}.
+cioè una \textsl{perdita di memoria}.
Un caso tipico che illustra il problema è quello in cui in una subroutine si
alloca della memoria per uso locale senza liberarla prima di uscire. La
che contiene l'errore. Per questo motivo è sempre molto difficile trovare un
\textit{memory leak}.
-Per ovviare a questi problemi l'implementazione delle routine di allocazione
-delle \acr{glibc} mette a disposizione una serie di funzionalità che
-permettono di tracciare le allocazioni e le disallocazione, e definisce anche
-una serie di possibili \textit{hook} (\textsl{ganci}) che permettono di
-sostituire alle funzioni di libreria una propria versione (che può essere più
-o meno specializzata per il debugging).
+In C e C++ il problema è particolarmente sentito. In C++, per mezzo della
+programmazione ad oggetti, il problema dei \textit{memory leak} è notevolmente
+ridimensionato attraverso l'uso accurato di appositi oggetti come gli
+\textit{smartpointers}. Questo però va a scapito delle performance
+dell'applicazione in esecuzione.
+
+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é il
+framework gestisce automaticamente la cosiddetta \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 performance dell'applicazione in esecuzione
+(inoltre le applicazioni sviluppate con tali linguaggi di solito non sono
+eseguibili compilati, come avviene invece per il C ed il C++, ed è necessaria
+la presenza di una infrastruttura per la loro interpretazione e pertanto hanno
+di per sé delle performance più scadenti rispetto alle stesse applicazioni
+compilate direttamente). Questo comporta però il problema della non
+predicibilità del momento in cui viene deallocata la memoria precedentemente
+allocata da un oggetto.
+
+Per limitare l'impatto di questi problemi, e semplificare la ricerca di
+eventuali errori, l'implementazione delle routine di allocazione delle
+\acr{glibc} mette a disposizione una serie di funzionalità che permettono di
+tracciare le allocazioni e le disallocazione, e definisce anche una serie di
+possibili \textit{hook} (\textsl{ganci}) che permettono di sostituire alle
+funzioni di libreria una propria versione (che può essere più o meno
+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
+ \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}
Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
-problemi di memory leak descritti in precedenza, è la funzione \func{alloca},
-che invece di allocare la memoria nello heap usa il segmento di stack della
-funzione corrente. La sintassi è identica a quella di \func{malloc}, il suo
-prototipo è:
+problemi di \textit{memory leak} descritti in precedenza, è la funzione
+\func{alloca}, che invece di allocare la memoria nello heap usa il segmento di
+stack della funzione corrente. La sintassi è identica a quella di
+\func{malloc}, il suo prototipo è:
\begin{prototype}{stdlib.h}{void *alloca(size\_t size)}
Alloca \var{size} byte nel segmento di stack della funzione chiamante.
La memoria non viene inizializzata.
La funzione restituisce il puntatore alla zona di memoria allocata in caso
- di successo e \macro{NULL} in caso di fallimento, nel qual caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
\var{errno} assumerà il valore \macro{ENOMEM}.
\end{prototype}
\noindent ma in questo caso non è più necessario liberare la memoria (e quindi
della fine del segmento dati.
La funzione restituisce il puntatore all'inizio della nuova zona di memoria
- allocata in caso di successo e \macro{NULL} in caso di fallimento, nel qual
+ allocata in caso di successo e \val{NULL} in caso di fallimento, nel qual
caso \macro{errno} assumerà il valore \macro{ENOMEM}.
\end{functions}
\noindent in genere si usa \func{sbrk} con un valore zero per ottenere
Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e
per i programmi normali è sempre opportuno usare le funzioni di allocazione
standard descritte in precedenza, che sono costruite su di esse. L'uso di
-queste funzione è ristretto alle specifiche necessità di chi debba
+queste funzioni è ristretto alle specifiche necessità di chi debba
implementare una sua versione delle routine di allocazione.
Come per la lista dei parametri anche questa lista è un array di puntatori a
caratteri, ciascuno dei quali punta ad una stringa, terminata da un
-\macro{NULL}. A differenza di \var{argv[]} in questo caso non si ha una
+\val{NULL}. A differenza di \var{argv[]} in questo caso non si ha una
lunghezza dell'array data da un equivalente di \var{argc}, ma la lista è
terminata da un puntatore nullo.
Esamina l'ambiente del processo cercando una stringa che corrisponda a
quella specificata da \param{name}.
- \bodydesc{La funzione ritorna \macro{NULL} se non trova nulla, o il
+ \bodydesc{La funzione ritorna \val{NULL} se non trova nulla, o il
puntatore alla stringa che corrisponde (di solito nella forma
\cmd{NOME=valore}).}
\end{prototype}
Una modalità diversa, che può essere applicata solo quando il tipo dei
parametri lo rende possibile, è quella che prevede di usare un valore speciale
come ultimo argomento (come fa ad esempio \func{execl} che usa un puntatore
-\macro{NULL} per indicare la fine della lista degli argomenti).
+\val{NULL} per indicare la fine della lista degli argomenti).
\subsection{Potenziali problemi con le variabili automatiche}