Newsgroup: it.comp.lang.c
Titolo: malloc in segfault

Allora: oggi ho perso tutto il di' dietro un segfault provocato da una
chiamata a malloc. Nel codice in questione ce ne sono numerose, ma solo
una e' quella incriminata.
Per farla breve: ho fatto girare gdb sull'applicazione e si vede che e'
proprio un errore di malloc, nella libc. Per sfizio, ho messo qualche
free qua e la', ed ho notato che l'errore si e' "spostato": invece di
andare ad intaccare una particolare chiamata a malloc, tutto saltava su
un altra (o sulla stessa, all'interno della stessa funzione chiamata
piu' volte).
Quando poi ho rimesso tutto come all'inizio... Cilecca, l'errore e'
rimasto laddove stava l'ultima volta...
Ho googlato un po' in proposito fino a trovare un riferimento nelle FAQ
di comp.lang.c ( 
http://www.eskimo.com/~scs/C-faq/q7.19.html
 ): peccato
che accenni ad errori di free (al momento del primo errore non c'era un
free che fosse uno [ehm... Vabbe', non e' una cosa tanto bella ;-) ], o
a errori in precedenti chiamate a realloc (ce ne saran si e no tre,
tutte guardate e verificate: a posto).
A questo punto non mi resta che affidarmi all'esperienza altrui, dato
che i manuali fanno riferimento a casi diversi dal mio: e' gia' successo
ad altri? In che modo e' stato risolto il tutto?
Grazie :-)
-- 
Roberto -MadBob- Guido
mail bob4mail***@***
gmail.com
web 
http://madbob.homelinux.com
BrainTop Project maintainer - 
http://braintop.sf.net

 che accenni ad errori di free
Leggi meglio, la spiegazione data e` perfettamente attinente al tuo
codice:
"It is unfortunately very easy to corrupt malloc's internal data
 structures [...] The most common source of problems is writing more to
 a malloc'ed region than it was allocated to hold"
In pratica, da qualche parte nel tuo programma, stai sforando dalla
memoria allocata e stai andando a sovrascrivere parti della strutture
dati usate dall'allocatore per tenere traccia della memoria in uso.
Puoi affidarti ad uno dei vari debugger per la memoria (VC mi pare che
ce l'abbia integrato, sotto linux Valgrind e` ottimo).
Luca
-- 
Home: 
http://kronoz.cjb.net
Alcuni pensano che io sia una persona orribile, ma non e` vero. Ho il
cuore di un ragazzino - in un vaso sulla scrivania.

 Grazie :-)
si certo, č successo a tutti direi :) mi sembra il tipico errore derivato
da un overflow sulle strutture dati che utilizza malloc & co.
Spiegandomi meglio. Se mallochi una certa area di memoria, e poi ci scrivi
sopra piu di quanto spazio hai richiesto, otterrai un errore (segfault)
non nel momento in cui scrivi, ma in una non ben precisa futura chiamata
ad un'altra *alloc()... ragion per cui č anche il piu rognoso da scovare
quest'errore.
M`

 
Cio' vuol dire che il fatto che tutto crashi *esattamente* quando viene
invocata una malloc non e' influente, ma dipende da un punto non meglio
precisato del codice??? E non dovrebbe andare in segfault nel momento in
cui si va a scrivere "fuori dal seminato"?
Oh, cielo: prevedo una lunga giornata di debugging, domani...
Vabbe': grazie mille per i chiarimenti :-) !


cui si va a scrivere "fuori dal seminato"?
No. Questo purtroppo e' un mito che ha una certa diffusione.
Se accedi fuori dai limiti non e' affatto detto che tu
ottenga un segfault... anzi... le probabilita' che questo
accada sono in genere scarse (a meno di utilizzare tool
speciali dedicati a questo).
Quello che invece in genere accade quando scrivi fuori
dai limiti e' che semplicemente scassi i dati di
qualcun'altro... o dati di un'altra parte del tuo
programma oppure parte delle strutture dati usate
internamente dalla libreria (e la struttura dati dello
heap usato da malloc/free e' di gran lunga la vittima
piu' frequente).
Spesso quando ricevi il segfault la segnalazione non ti
arriva dal punto in cui e' avvenuto il danno... ma solo
dalla "vittima" che chiede di fare stupidate perche'
qualcun altro gli ha scombinato le carte in tavola.
Non e' raro che il danno reale sia avvenuto qualche
milione di istruzioni eseguite prima.
Oltre allo sconfinamento casi abbastanza frequenti sono
il continuare ad utilizzare una struttura che e' stata
deallocata (e la cui memoria era di conseguenza magari
gia' stata data ad altri) oppure fare piu' volte "free"
dello stesso blocco dati.
HTH
Andrea

 cui si va a scrivere "fuori dal seminato"?
Quando "sfori" non è affatto detto che l'errore venga fuori subito (anzi,
direi che _molto spesso_ non è così).  Ad esempio, a me è capitato di
dover sbattere la testa su del codice (scritto da me, ahimè), in cui una
funzione scriveva "fuori dal seminato" e da tutt'altra parte del codice
falliva una innocentissima fopen().  Io indagavo sui motivi per cui
fallisse la fopen() ma in realtà il problema era da tutt'altra parte. 
Questo tipo di errori sono purtroppo i nemici più subdoli che si possano
avere in programmazione, perché alla fine si potranno anche scovare, ma ti
avranno fatto perdere interi giorni di debug :-(
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 
Mumble mumble... Vabbe', ora non ho il codice sottomano ma appena
possibile verifichero' dove potrebbe stare l'errore: fortunatamente il
segfault si manifesta in una delle fasi iniziali del codice, dunque le
operazioni che lo precedono (e dunque tutte potenziali responsabili) non
sono poi tantissime.
Qualche post fa e' stato accennato all'esistenza di debugger specifici
per aiutare in casi come questo (o comunque rivolti al debugging delle
aree di memoria usate): premesso che solitamente non uso neppure gdb
(trovo le "printf strategiche" piu' pratiche ;-) ), quali potrebbero
essere tali debugger? Qualche nome?
Grazie ancora :-)


essere tali debugger? Qualche nome?
Io nei programmi C uso sempre una mia versione di malloc che nella
configurazione minima non fa altro che terminare il programma in
caso di fallimento (testare tutte le allocazioni e' secondo me
semplicemente assurdo per diversi motivi che non e' il caso di
elencare qui). Nella versione "debug" fa un po' di cose in piu'...
in particolare
  - Verifica che i valori passati a free siano effettivamente
    di blocchi restituiti da malloc.
  - Sistema un "bordo" prima e dopo i blocchi allocati
    e riempe questa area con pattern specifici per scoprire
    se qualcuno ci scrive dentro.
  - Quando un blocco viene liberato lo riempe interamente
    con un pattern specifico e mette il blocco in una lista
    libera. Al momento del riutilizzo del blocco prima di
    consegnarlo al richiedente verifica che il pattern sia
    ancora intatto. Scriverci un pattern aiuta a scoprire
    se qualcuno legge dei dati dopo che sono stati deallocati,
    verificare il pattern serve a scoprire se qualcuno scrive
    in un blocco gia' deallocato.
  - Registra il nome del file sorgente e la linea di codice
    che ha fatto l'allocazione cosi' che in caso di problemi
    possa fornire queste informazioni (utilissime nei casi
    di memory leak).
  - Puo' periodicamente verificare che tutto sia in ordine
    (ovvero che tutti i blocchi allocati abbiano il "bordo"
    ancora sano, che quelli liberati e in attesa di riuso
    non siano stati toccati). Questo e' utile per cercare
    di isolare il momento in cui viene fatto il danno.
Ci sono tool commerciali che fanno questo e altro... i piu'
famosi una volta erano Purify e BoundsChecker; Electric Fence
e' una libreria free blocca il programma al momento di uno
sconfinamento (e' inclusa in molte distribuzioni linux).
HTH
Andrea

 
Ah, si: questo Electric Fence non mi e' nuovo, ma, non avendone mai
avuto bisogno, non mi sono mai documentato in proposito.
Non e' mai troppo tardi ;-)
