Newsgroup: it.comp.lang.c
Titolo: Disallocare: quando ha senso farlo?

Ciao a tutti e scusate la niubbaggine ;),
il mio professore di informatica di solito non ci richiede mai di 
disallocare la memoria a fine programma, ma guardando i testi d'esame di 
altri professori ho notato che alcuni addirittura pretendono che sia fatta 
*sempre*.
Ho fatto un piccolo test con un programma idiota su windows (con linux non 
avrei saputo come fare). Se eseguo questo codice:
***
#include <stdio.h>
#include <stdlib.h>
float matr[5000][5000];
int main()
{
     while(malloc(sizeof(matr)));
     getchar();
     return 0;
}
***
e vado sul "task manager" di windows, vedo che viene allocata tutta la 
memoria disponibile. Se premo invio, però, il programma termina e la memoria 
viene liberata completamente! Questo significa che il compilatore provvede 
da sé a disallocare, oppure è gestito a livello di sistema operativo? E' un 
comportamento standard e che funziona per ogni OS? Dunque ha senso 
disallocare solo quando so che passa molto tempo tra l'allocazione e la 
chiusura del programma e che nel frattempo altri programmi potrebbero 
richiedere memoria e non trovarla?
ciau, grazie! 

 richiedere memoria e non trovarla?
Per un programma di breve durata può essere ininfluente, ma uno che 
sia in esecuzione per molto tempo potrebbe causare perdite che nel 
tempo renderebbero indisponibile la memoria ad altri programmi (o 
perlomeno obbligare il SO a swappare).
In ogni caso è buona norma di programmazione rilasciare le aree 
allocate quando non vengono più usate.  I programmi di analisi della 
qualità del codice in genere segnalano questa condizione.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

 qualità del codice in genere segnalano questa condizione.
Programmi di analisi della qualità... uhm, questa è nuova per me :). Ne 
esistono di gratuiti (o di open source)? Sarebbe curioso capire quali sono i 
parametri valutati, e in che misura.
ciao,
 Dario 

 compilatore o dal sistema operatio?
Non so se e' totalmente standard,
ma sicuramente un qualunque s.o. ragionevole
liberera' tutta la memoria allocata da un programma che termina.
Anche per evitare che un programma che si "pianta" a meta'
possa lasciare memoria bloccata.
Sicuramente e' una buona cosa almeno avere presente il problema
della disallocazione e in generale, nel caso di programmi un po'
complessi, avere ben chiaro come evolve nel tempo l'occupazione
di memoria.
In linea di principio sarebbe una buona abitudine
disallocarla esplicitamente e certamente se un programma gira per 3 ore
e usa per il 10% del tempo 300Mega di ram e nel restante 90% di tempo 5
Mega, allora disallocare i 300Mega e' sicuramente qualcosa da considerare.
Se invece l'uso di memoria cresce in modo monotono nel tempo allora
potresti anche decidere di non disallocare esplicitamente
alla fine del programma.
Dipende anche un po' dalla situazione:
E' chiaro che se all'inizio hai fatto una malloc(100*1024*1024)
fare una singola free() alla fine non ti costa tanto, come tempo-uomo.
Se pero' hai allocato dinamicamente una struttura dati incasinatissima
(uno heap di alberi di liste di alberi di vettori dinamici...)
che ti e' costata magari mezzo milione di allocazioni,
allora invece di scrivere una procedura ricorsiva altrettanto
incasina per liberare pezzo dopo pezzo tutta la memoria
(col rischio di introdurre qualche errore nel programma...)
tanto vale far fare la disallocazione in automatico al s.o.
ciao,
g.

 *sempre*.
Gli altri professori mi stanno più simpatici. In generale, è buona regola
insegnare che la memoria va *sempre* deallocata; per la serie: andiamo sul
sicuro. Poi, altrettanto in generale, i sistemi operativi recuperano la
memoria alla fine dei processi.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


Per ambiente unix conosco splint o il piu` vecchio lint.  Non sono 
proprio per l'analisi della qualità ma per l'analisi statica del 
codice e rilevano problemi di vulnerabilità ed errori di 
programmazione.  Segnalano memoria non rilasciata con warning.
Altri tools che ho usato sono a pagamento e piuttosto costosi.


compilatore o dal sistema operatio?
Le routine di allocazione/deallocazione della memoria fanno parte
della libreria standard (prototipi in stdlib.h), ma il compilatore non
*gestisce* nulla, traduce il codice da sorgente a eseguibile (un tempo
le fasi compilazione + linking erano visibilmente separate, quindi
prima compilavi e poi linkavi; ora, nella maggior parte dei casi, se
si vuole, lo step può essere unico). A seconda della piattaforma su
cui il codice è destinato a girare, poi, le routine di
allocazione/deallocazione presenti in libreria, saranno mappate sulle
omologhe routine del sistema operativo (es.:
VirtualAlloc()/VirtualFree()).

 richiedere memoria e non trovarla?
Disallocare la memoria è sempre cosa buona e giusta, soprattutto in un
programma in cui si alloca (anche piccole quantità) memoria
continuamente. Anche perchè considera che quando si raggiunge tutta la
memoria fisica disponibile ed il S.O. comincia a swappare su disco, le
prestazioni decrescono fino al bloccaggio della macchina.
Almeno questo è il problema che ho avuto qualche mese fa con un
software in cui mi dimenticavo di disallocare la memoria allocata da
un puntatore.
Ciao,
     Fabrizio
=== 
http://www.negusweb.it
 ===

 un puntatore.
Gią. Questi sono i motivi che hanno spinto i linguaggi ad evolvere e fare
a meno dei puntatori, se non altro usati in maniera esplicita. Altri
linguaggi consentono di gestire le allocazioni/deallocazioni di memoria in
maniera automatica e "smart" in modo da scongiurare catastrofi come quella
che hai sperimentato. E nonostante tutto, un modo per usare dei puntatori
mascherati esiste sempre, vedi i reference del C++. Purtroppo, nonostante
i precetti di buona programmazione, molti linguaggi ad oggetti continuano
a non supportare degli idiomi (vedi RAII) essenziali per scrivere codice
sicuro.


 sicuro.
Beh, ma credo che per propria natura i linguaggi che utilizzano
puntatori soffriranno sempre di questi problemi.
Perchè se alloco memoria con un puntatore, è molto difficile fare un
controllo di deallocazione della stessa. Perchè questa potrebbe
avvenire nella stessa routine o in qualsiasi altre parti del
programma.
Ciao,
    Fabrizio

programma.
Be', in C++ hanno introdotto gli "smart pointers" che hanno un
controllo dei puntatori "posseduti" molto sicuro.

 Altri tools che ho usato sono a pagamento e piuttosto costosi.
Ho fatto un paio di googlate... da quanto ho capito, se ho usato la query 
giusta, si limitano comunque a un'analisi *statistica* e a segnalare 
protezioni per evitare il buffer overflow e cose di questo tipo, ma --  
correggimi se sbaglio -- non esistono tools che riescano addirittura a 
calcolare la f(x) ordine dell'algoritmo usato [ O(f(x)) ] e a suggerire 
soluzioni più efficienti, giusto?
Sarebbe anche un qualcosa di estremamente difficile da implementare, credo 
:). 


File tst.c :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
   char *buffer = malloc(1000);
   sprintf(buffer, "Questo e` un esempio ;-)\n");
   return 0;
}
$  flexelint /usr/lib/flexelint/co-gcc.lnt -I /usr/include tst.c
FlexeLint for C/C++ (U32) Ver. 7.50n, Copyright Gimpel Software 1985-1998
--- Module:   tst.c
    sprintf(buffer, "Questo e` un esempio ;-)\n");
tst.c:9 (Warning:668) - Possibly passing a null pointer to function 
sprintf(signed char *, const signed char *, ...), arg. no.  1
    return 0;
tst.c:10 (Warning:429) - Custodial pointer 'buffer' (line 7) has not 
been freed or returned
}
tst.c:11 (Info:715) - argv (line 5) not referenced
tst.c:11 (Info:715) - argc (line 5) not referenced
    --- Wrap-up for Module: tst.c
: (Info:766) - Header file '/usr/include/unistd.h' not used in module 
'tst.c'
COme vedi son semplici messaggi informativi per segnalare situazioni 
che possono diventare potenzialmente pericolose.  Più basso è il 
numero del messaggio più grave è la segnalazione.


Outspan ha scritto:

In teoria quello credo sia un problema np-completo...

 programma.
Beh, un tool di analisi statica (intraprocedurale) che facesse anche
analisi di aliasing potrebbe dire qualcosa a riguardo. Per esempio
potrebbe provare che nessun alias del puntatore cui è stato assegnato
originariamente il buffer è mai argomento di una free.
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.

 soluzioni più efficienti, giusto?
in ricerca probabilmente qualcuno che lavora sull'ordine esiste. dopo
tutto anche nel gruppo del mio relatore stanno facendo lavori sulla
terminazione per potere dire qualcosa [ n.b. la cosa impossibile
ontologicamente è un programma che *per ogni* programma dice se termina
o meno, non un programma che 'prova' a scoprire se il suo input termina
].
Dicevo, in ques'ottica si può probabilmente anche andare a calcolare il
costo. Con le mie relativamente poche conoscenze di analisi astratta,
qualcosina in certi casi mi verrebbe in mente che si possa dire in un
buon numero di casi (specie lasciando fuori i goto).
Ma è ribadisco tutta roba parecchio tecnica e cazzuta. Suggerire
soluzioni più efficienti fuori dai casi banali, mi pare sostanzialmente
fantascienza.
Ma sono solo uno studente.
