Newsgroup: it.comp.lang.c
Titolo: Segnalare errore nella malloc

Ciao a tutti.
Avrei il seguente problema:
 
ogni qual volta devo utilizzare l'istruzione malloc per riservare un blocco di memoria, mi preoccupo sempre di verificare che il puntatore non sia NULL.
 
Questo modo di programmare pero' mi appesantisce un po' il codice.
 
Per snellirlo allora ho deciso di utilizzare una subroutine (malloc_chk) che si preoccupa di verificare se c'e' stato un problema. 
 
Mi resta pero' ancora un grattacapo, come segnalare dove e' accaduto il problema.
 
Al momentosto sto utilizzando degli id numerici i quali dovrebbero essere tutti
diversi per garantirmi l'univocita' della eventuale segnalazione. Scrivendo il codice pero' mi sono reso conto che questo metodo non e' decisamente il massimo.
 
Ogni tanto devo ripassarmi tutto il sorgente per risistemare gli id.
 
Non avreste una soluzione alternativa?
 
Grazie


 
SE ho capito il tuo problema, io faccio una cosa
orribilmente zozza, ovvero passare a routines di questo
genere anche il nomefile e numero di linea, almeno
rintraccio dove sta il probema. Ci sono macro già definite
e puoi fare qualcosa del genere:
 
void  *myalloc (__FILE__,__LINE__,size, etc);
 
adesso sarò lapidato, lo so :D
 
Certo che se la velocità è un parametro critico, mettere
altri due parametri sullo stack non è il massimo... e ci
vorranno soluzioni più sofisticate, per esempio una
compilazione condizionale per sostituire la routine di
allocazione con una versione "release".
 
 
-- 
Un corpo immerso in un liquido si bagna.
Un corpo immerso nel cemento sapeva troppo.
Un corpo immerso in un altro corpo si diverte.
Un corpo immerso in due corpi è un'orgia.
 


 
 
Basta trasformare myalloc in macro e il client non deve specificare 
__FILE__ e __LINE__
Inoltre non soffre di una ulteriore chiamata a funzioni
 


[CUT]
 
Se l' esito dell'  allocazione non deve essere
gestita in nessun modo dal client
basta fare un abort in caso di allocazione non riuscita
Per il resto basta una macro dove usi __FILE__ e __LINE__
 

 Mi resta pero' ancora un grattacapo, come segnalare dove e' accaduto il problema.
 
Già ti dissero.
 
Aggiungo che invece di appesantire la chiamata a malloc con __FILE__ e
__LINE__ potresti sollevare un'eccezione e lasciare che sia l'handler a
segnalare dove e quando malloc è fallita. Già che c'è, un handler
potrebbe pure fare qualche check diagnostico e dare altre info, dato che
a quel punto il tempo di esecuzione non è più un fattore critico :-)
 
 


In C non esiste una vera gestione delle eccezioni
E' comunque possibile fare qualcosa con l' accoppiata setjmp/longjmp
 
Un esempio:
 
http://www.on-time.com/ddj0011.htm
 
 

 
 
Come ti hanno già detto puoi wrappare la malloc ma, io la butto lì, il tuo
problema non è la malloc, ma la gestione del flow degli errori. Se hai
un errore che riguarda un altra cosa che fai? Non puoi usare lo stesso flow
per gli errori sulle funzioni di allocazione?
 
Ciao!


Prima di tutto un doveroso GRAZIE A TUTTI.
Credo che la soluzione ottimale per me sia la macro __LINE__ di cui ignoravo la conoscenza (e probabilmente ci saranno ancora tante altre cose che ignoro).
Usando quasi sempre un unico file la macro __FILE__ restiruirebbe sempre il medesimo nome del sorgente (differente sarebbe se le varie subroutine fossero in file separati. In ogni caso ho scoperto la presenza di __func__ che restituisce il valore della funzione).
 
Per cultura personale mi piacerebbe anche capire cosa sono e come funzionano gli handler di cui parla Massimo Soricetti. Potreste indicarmi un esempio valido?
 
Grazie ancora.

 In C non esiste una vera gestione delle eccezioni
 
Vero, ma uno può pure affidarsi al sistema operatyivo, x esempio soto
windows si possono installare gestori usando le API SEH... sotto linux
non so, ma suppongo che qualcosa ci sia pure lì
 


Ma non è portabile
Sotto linux, essendo unix, non esistono le eccezioni tipo SEH
Al massimo esistono i segnali
 


 
Continuo a dire che hai un problema d'organizzazione del codice.
Spezzetta prima in funzioncine piccole, poi in file, poi ti accorgi che
controllare due/tre volte se un'allocazione ritorna NULL è una roba che non
da fastidio.
 
Ciao!

 Al massimo esistono i segnali
 
Che assolvono gli stessi compiti. Quindi, di nuovo, problemi zero.
 

 mi piacerebbe anche capire cosa sono e come funzionano gli handler
 
Un handler (per esteso exception handler; gestore di eccezioni, tradotto
in italiano) è un pezzo di codice a cui il tuo programma salta
automaticamente quando si verifica un'eccezione di un certo tipo (quale
handler deve trattare quale eccezione lo decidi tu). Lo scopo degli
handler è quello di metterci una pezza, se possono, altrimenti terminare
il programma in modo un pò meno cinofallico.
Esempio di eventi che generano eccezioni: divisione per zero, underflow,
overflow.
 
Puoi definire tu delle eccezioni tue oltre a quelle definite dal
sistema, se ti fa comodo: io suggerivo proprio di creare un'eccezione
apposta per l'out of memory della malloc e chiamarla da software (in
gergo "lanciare un'eccezione", "sollevare un'eccezione").
 
In C++ la gestione delle eccezioni è più completa, in C normale invece è
molto primitiva.
 
Anche i sistemi operativi moderni, a prescindere dal linguaggio di
programmazione quindi, forniscono meccanismi per la gestione delle
eccezioni: sotto Windows ci sono gli Structured Exception Handler, sotto
Linux c'è il meccanismo dei segnali (SIG_TERM, SIG_HUP ecc. ecc.).
Chiaro che sono sistemi non portabili: se decidi di usarli, quando fai
il porting sono 'azzi tuoi, come diceva enoquick


I segnali sono pochi e non portabili, in piu non portano informazioni se 
non il numero del segnale stesso
Meglio una accoppiata setjmp/longjmp, non hanno limiti di uso e sono 
portabili
Avevo già portato un url con esempi che riporto:
 
http://www.on-time.com/ddj0011.htm
 
 
 
 
 
 

 [...]
 
P.S.: scusate per il quoting, sto usando google groups
 
Ciao  Manlio

 
 
Pur'io, ma cancello le linee in più ;)
 
Ciao!

Grazie


Non solo.  Dalla textarea per l'editing dei messaggi, le linee lunghe avevano il quoting rotto, ma sembra che il testo inviato sia corretto.
 
 
Ciao  Manlio

 dove my_log, ad esempio, � una macro che in caso di debug stampa su stderr anche __FILE__ e __LINE__,
 
Cosi' pero' se my_log e' una macro e viene espansa dentro il wrapper il
risultato sara' che verrano loggati sempre gli stessi valori di
__FILE__ e __LINE__ (quelli corrispondenti alla riga dentro il wrapper).
E' il wrapper che dovrebbe prevedere i paramentri di input per
__FILE__ e __LINE__ e poi si dovrebbe definire una macro per il
wrapper...
 

 wrapper...
 
 
#define my_log(msg) my_log_core(__FILE__, __LINE__, msg)
 
Mi sembrava ovvio.
 
 
Ciao  Manlio


Credo che si riferisca al fatto che anche definendo my_log in quel
modo i valori di __FILE__ e __LINE__ si riferiscono a file e riga della
funzione my_malloc quindi sono sempre gli stessi, mentre bisognerebbe
vedere file e riga della *chiamata* a my_malloc().
 
Probabilmente la soluzione e' di definire anche my_malloc come macro
invece che come funzione.
 
ciao
Giacomo


E poi si vuole sapere dove è stata chiamata quella funzione e via dicendo
Uno stack delle chiamate (stack frame)
Non esiste un modo portabile per avere lo stack frame
Meglio un abort, al  massimo abilitare la produzione del core file e se 
proprio si vuole vedere lo stack delle chiamate lasciare i simboli di 
debug ed usare il debugger per verificare lo stack frame
 
 
 
 
 
 

 [...]
 
 
Ciao  Manlio

 Mi sembrava ovvio.
 
Anche a me... :-)
 
 

 
 
parecchi anni fa su Macintosh usavo quanto illustrato qui:
 
 
http://www.mactech.com/articles/develop/issue_11/Parent_final.html
 
 
da qualche parte in rete si dovrebbe trovare ancora Exceptions.h
 
U
 
 
----Android NewsGroup Reader----
http://www.piaohong.tk/newsgroup