Newsgroup: it.comp.lang.c++
Titolo: Allocazione di mem incomprensibile di egcs con -O(n>0) ed inline

]

 -createNewBuffer alloca con new un nuovo buffer
E` un "buffer" di 1 singolo carattere?  O lo alloca con new[]?
Perche`, se lo alloca con new-con-le-quadre, deve essere
rilasciato con delete-con-le-quadre, cioe` "delete[] buffer",
non "delete buffer" come qui sopra segnato.  (questo e`
cruciale in C++ Standard, non so se egcs sia suscettibile
a questo errore in questo caso particolare).
Piu` in generale, se il modo di allocazione di un "coso" e`
incapsulato in un "robo", sara` meglio che il modo di
DE-allocazione dello stesso coso sia nello stesso robo.
Ad esempio, se un "buffer" e` creato dalla funzione
createNewBuffer in un certo sorgente, sara` meglio
che venga liberato da una funzione deleteBuffer nello
stesso sorgente; cosi`, e` piu` agevole mantenere
allineate le strategie di allocazione e deallocazione,
cosa assolutamente cruciale.
Ancora piu` importante, non capisco perche` hai la
necessita` di lavorare cosi` a basso livello.  Nel 99%
dei casi, un std::vector<char> (dimensionato con
la sua funzione .resize(), ecc) e` piu` comodo ed ha
prestazioni equivalenti a quel che puoi fare con un
new[]/delete[], con molto meno trabocchetti strani
che ti aspettano al varco.
Alex

che ti aspettano al varco.
Perche' e' la parte piu' a basso livello di un sistema di
messaggistica fra processi; il buffer e' il buffer interno dei
messaggi, e per come vengono manipolati e' meglio avere a che fare con
dei char* (anche perche' vengono scambiati milioni di messaggi di
piccole dimensioni, a questo punto non credo che vector<char> sia
concorrenziale per prestazioni)


 concorrenziale per prestazioni)
Uno std::vector<char>:: iterator e` appunto un char*, quindi
i char* non sono poi lontani:-).  Possibile che l'overhead di
"scambio di messaggio" e quello di "alloca e libera memoria,
magari piu` volte" non siano tali e tanti da annullare (rendere
non misurabile!) la differenza di prestazioni che puo` dare
std::vector...?  Considera ad esempio il fatto che "distruggi
il vecchio buffer e ne allochi uno nuovo", dove, con vector,
faresti solo .resize(), che, spesso, puo` implicare una qualche
ottimizzazione interna; questo risparmio potrebbe gia` da solo
ripagare tutto l'eventuale costo.
Comunque, io non _inizierei_ con applicare ottimizzazioni
che, a mio parere, sono rarissimamente appropriate, come
l'uso di meccanismi di bassissimo livello come new[]; mi
pare piu` sensato implementare dapprima un codice piu`
normale, usando le normali strutture come std::vector;
poi, _se_ le misurazioni e i gprof mostrano che in effetti
gli std::vector rendono inaccettabili le prestazioni, puo`
essere il momento di sciorinare tutta la panoplia delle
ottimizzazioni di bassissimo livello, compreso new[] (e
comprese strategie speciali di gestione della memoria
dinamica che possono risparmiare moltissimo rispetto a
new[]/delete[], e sono piu` facili da applicare a codice
che usa std::vector, che non a codice che usa gia` le
cose di bassissimo livello...).
Alex

 delle cose stranissime.
Potrebbe anche essere un bug del compilatore.
EMG

 che ti aspettano al varco.
Due appunti; piuttosto che con resize() io interverrei con reserve().
Evita l'overhead da riallocazioni, ed in piu' non richiama il
costruttore default per ogni elemento che, per strutture complesse,
puo' essere importante.  Infine, perche' crearsi dei problemi?  Si
puo' curare il problema ala radice se il metodo incriminato restituisce
non un pointer-to-char ma un auto_ptr<char>.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 non un pointer-to-char ma un auto_ptr<char>.
Questo puo` funzionare se e solo se il buffer e` di un solo
carattere, allocato con new senza parentesi quadre, caso
molto raro.  Se il buffer e` allocato con new[], mettere il
puntatore in un auto_ptr e` un gravissimo bug, in quanto,
nel suo distruttore, l'auto_ptr fara` delete senza []; e di
nuovo avrai undefined behavior.
std::auto_ptr<> NON serve per tenere un puntatore ad un
array, ma SOLO, ESCLUSIVAMENTE per un puntatore ad un
singolo oggetto.
Per molteplici oggetti, std::vector e` il miglior modo di
non "crearsi dei problemi".
Alex

 singolo oggetto.
Hai ragione; ho detto una grossa scemata.


 vettore e subito dopo reserve; intendevo questo.
Se sai gia` quale capacity ti servira`, ma per ora non ti
serve tutta come size, reserve e` effettivamente una
valida ottimizzazione.
Alex

poi, _se_ le misurazioni e i gprof mostrano che in effetti
[...]
Hai ragione, ma c'e' anche un'altra ragione che non avevo detto, molto
piu' pratica: all'inizio quel codice era in C puro; all'inizio non era
una ottimizzazione ma l'unico modo di farlo :) Visto che era cosi' e
funzionava, mi sembrava inutile riscrivere molto piu' codice del
dovuto per avere qualcosa di piu' 'pulito', ma pob. meno veloce.
Cmq alla fine sono stato punito :( 



Ne sono quasi convinto, anche cancellando con delete [] come sarebbe
giusto fare da' un segmentation fault (notare che viene instanziato
anche in un altro punto del programma senza problemi). Non so pero'
come classificarlo o se segnalarlo: a parte in quel punto di codice
non sembra riproducibile.
Alla fine usando uno std::vector<char*> (come consigliato da Alex)
sembra comportarsi bene.
