Discussione:Codice rientrante

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca

>> Il codice non deve nè allocare nè deallocare aree di memoria, nè nello heap nè altrove (nel caso del C, non deve assolutamente usare nè malloc(), nè free(), nè le loro varianti; in Pascal non si devono usare nè new, nè dispose);

A quanto ne so io, in realtà, il problema non è tanto quello di allocare memoria in se, quanto piuttosto il fatto di utilizzare le funzioni malloc e free che utilizzano per i loro scopi variabili statiche mandando a pallino la rientranza del codice. Avendo a disposizione delle funzioni di allocazione di memoria rientranti non ci dovrebbero essere problemi, anzi, l'utilizzo di memoria allocata dinamicamente dovrebbe portare dei benefici. Qualcuno può confermare?

Dino 15:16, Giu 29, 2005 (CEST)

Il punto è che se una routine alloca un blocco memoria, il puntatore a questo blocco deve essere salvato da qualche parte: ma se poi la routine stessa viene interrotta mentre lavora (e chiamata da un altro programma, per un servizio completamente diverso dal primo) prima che abbia rilasciato la memoria allocata... la routine RIALLOCHERA' altra memoria per servire la seconda chiamata sovrascrivendo l'indirizzo del vecchio puntatore: in uscita deallocherà correttamente la seconda allocazione, poi tornerà al primo servizio, lo finirà... e proverà a deallocare un'altra volta lo stesso blocco che aveva allocato prima (sollevando un errore), perchè il vecchio puntatore non è stato salvato. E il primo bolcco di memoria non verrà più deallocato (=memory leak). Una routine rientrante può benissimo usare variabili statiche, perchè sono uguali per tutte le chiamate, ma non può crearsi variabili dinamiche da sola: se necessario, è il programma chiamante che alloca (prima) un blocco di RAM e passa come parametro il puntatore alla routine, e provvede poi a disallocare la RAM allocata dopo aver chiamato la routine. Questo va bene perchè così il puntatore al blocco di memoria è memorizzato dal programma chiamante, che "se lo ricorda" a prescindere da cosa succede poi durnte la chiamata alla routine. Chiaro no? ehm ^_^ --Kormoran 02:22, Giu 30, 2005 (CEST)


Premetto che non sono un esperto in materia, quindi correggimi se sbaglio, ma c'è qualcosa che non capisco. Dal momento che le variabili automatiche sono allocate sullo stack (quello del programma chiamante) perchè una seconda istanza della routine dovrebbe sovrascrivere l'indirizzo del primo richiamo? Cerco di essere più chiaro. Prendi il codice qui sotto:

void f()
{
	char *pt;

	pt=(char *)malloc(1000);
	/* Fai qualcosa con la memoria allocata*/
	free(pt);
	return;
}

Premetto che do per scontato il fatto che le funzioni malloc e free siano rientranti. Se il codice viene chiamato da un processo A e poi interrotto durante l'esecuzione da un processo B, la variabile pt, essendo stata creata sullo stack di ciascun processo chiamante non interferisce con la copia dell'altro processo. Se così fosse non sarebbe neanche possibile scrivere codice ricorsivo dal momento che ciascun richiamo sovrascriverebbe i valori delle variabili del richiamo precedente. Se però, la variabile pt fosse statica, allora sì che sarebbero dolori, in quanto ci sarebbe una sola copia della variabile per tutti i richiami, in quanto verrebbe creata nello heap del modulo che contiene la funzione (come le global). Su una cosa però sono d'accordo. Le variabili statiche se usate correttamente non impediscono la rientranza del codice. Si possono usare per esempio come contatore per sapere quante istanze sono in esecuzione in quel momento. Che ne pensi?

Dino 16:10, Giu 30, 2005 (CEST)

Sulla nonrientranza di malloc() e free()[modifica wikitesto]

Secondo l'articolo linkato, malloc() e free() mantengono (a seconda dell'implementazione) una linked list internamente che mantiene dati sull'uso delle aree di heap. Suppongo sia protetto da una sezione critica (il che spiegherebbe perché è thread-safe) ma l'articolo spiega come se un handler di segnale personalizzato pianta malloc() o free() nel mezzo della manipolazione della linked list le cose possono diventare un pelo nonodeterministiche...

UHM in effetti per come la descrivi tu non ci sarebbe nessun problema se una funzione rientrante allocasse memoria... è possibile che io abbia preso un abbaglio. Il fatto che poi le cose possano pure andare storte è... come dire? Una cosa ovvia :) --Kormoran Lug 6, 2005 01:53 (CEST)

Allocare e usare memoria in una funzione durante un sighandler non è un problema; il problema è che hai una certa probabilità di mandare in malora la struttura interna usata da malloc, da cui casino per tutte le chiamate successive a malloc e free. Brutte cose.



Quando ho provato ad aprire l'articolo linkato qualche giorno fa non andava, ho pensato fosse un link morto, ma a quanto pare era solo un problema di connessione. Ad ogni modo, tirando le somme, viene fuori che le funzioni malloc() e free() sono, anche se dipende dall'implementazione, thread-safe ma non rientranti. Un link che ho trovato interessante è: http://blogs.msdn.com/oldnewthing/archive/2004/06/29/168719.aspx. C'è un bell'esempio proprio di una funzione del genere. Nè vien fuori che il problema non è l'allocare memoria in se, quanto utilizzare una funzione che lo faccia in maniera rientrante. Sospetto che, utilizzando al posto della malloc o delle sue varianti, le API di sistema non ci sarebbero problemi, anche se ovviamente vorrebbe dire sacrificare la portabilità. A patto, ovviamente, di avere a che fare con un kernel multitasking (Unix o NT), dubito che l'MS-DOS (e le sue shell Windows 3.1/9x/ME)abbia una rientranza particolarmente spinta. A questo punto modificherei l'articolo, se non ci sono obiezioni. Ce ne sono? In particolare sull'uso delle API di sistema?

Dino Lug 6, 2005 11:49 (CEST)

Nessuna obiezione, ma bisogna sottolineare la necessità di leggere la documentazione delle API del singolo sistema operativo, per correttezza.