Newsgroup: it.comp.lang.c++
Titolo: aiuto su template

salve a tutti,
sto avvicinandomi ai template e per provarne le potenzialità stavo
implementare una semplice lista lineare,
2 classi template, nidificate in un namespace chiamato LISTA_SEMPLICE
il codice è un po' lunghetto ma ve lo posterei volentieri se lo
chiedete,
// contiene gli elementi e la concatenazione della lista
template <class ELEMENTO> class CElementoNext  
{
private:
	// elemento successivo
	CElementoNext<ELEMENTO> *next;
private:
	// dati della lista
	ELEMENTO elemento;
public:
	// inserisco l'elemento
	POS Cerca(ELEMENTO&,POS&);
	// restituisco l'elemento
	ELEMENTO* operator[](POS&);
	// modifico l'elemento, riorganizzo l'ordine
	bool Modifica(ELEMENTO&);
	// elimino l'elemento
	bool Elimina(ELEMENTO&);
	// elimino l'elemento
	bool Elimina(POS&);
	// elemento successivo
	CElementoNext<ELEMENTO>* Next(){ return next; }
	// azzera riferimento elemento successivo
	void AzzeraNext(){ next= NULL; }
	// restituisco l'elemento
	bool operator<(ELEMENTO&);
	void Stampa(POS);
public:
	CElementoNext();
	CElementoNext(ELEMENTO&);
	CElementoNext(ELEMENTO&,CElementoNext<ELEMENTO>*);
	virtual ~CElementoNext();
};
// gestisce la lista
template <class ELEMENTO> class CListaNext  
{
private:
	// lista elementi
	CElementoNext<ELEMENTO> *lista;
public:
	// inserisco l'elemento
	POS operator[](ELEMENTO&);
	// restituisco l'elemento
	ELEMENTO* operator[](POS);
	// modifico l'elemento, riorganizzo l'ordine
	bool Modifica(ELEMENTO&);
	// elimino l'elemento
	bool Elimina(ELEMENTO&);
	// elimino l'elemento
	bool Elimina(POS);
	// elimino la lista
	void Elimina();
	// numero elementi
	POS Elementi(){ return totale_elementi; }
	void Stampa();
public:
	CListaNext();
	virtual ~CListaNext();
};
quando dealloco la memoria,
template <class ELEMENTO> CListaNext<ELEMENTO>::~CListaNext()
{
	if( lista )
		delete lista;
}
viene deallocata la memoria per qualche migliaio di elementi,
poi mi appare una finestra con questo messaggio:
ERRORE--->   Unhandled exception in "nome applicazione": 0xC00000FD:
Stack Overflow.
e mi posiziona sul codice disassemblato:
LISTA_SEMPLICE::CElementoNext<CStringa>::`scalar deleting destructor':
00403070   push        ebp
00403071   mov         ebp,esp
00403073   sub         esp,44h
---> 00403076   push        ebx		// posizione del puntatore fermo
00403077   push        esi
00403078   push        edi
00403079   push        ecx
0040307A   lea         edi,[ebp-44h]
0040307D   mov         ecx,11h
00403082   mov         eax,0CCCCCCCCh
00403087   rep stos    dword ptr [edi]
00403089   pop         ecx
0040308A   mov         dword ptr [ebp-4],ecx
0040308D   mov         ecx,dword ptr [ebp-4]
00403090   call       
@ILT+395(LISTA_SEMPLICE::CElementoNext<CStringa>::~CElementoNext<CStringa>)
(00401190)
00403095   mov         eax,dword ptr [ebp+8]
00403098   and         eax,1
0040309B   test        eax,eax
0040309D   je         
LISTA_SEMPLICE::CElementoNext<CStringa>::`scalar deleting
destructor'+3Bh (004030ab)
0040309F   mov         ecx,dword ptr [ebp-4]
004030A2   push        ecx
004030A3   call        operator delete (00404fb0)
004030A8   add         esp,4
004030AB   mov         eax,dword ptr [ebp-4]
004030AE   pop         edi
004030AF   pop         esi
004030B0   pop         ebx
004030B1   add         esp,44h
004030B4   cmp         ebp,esp
004030B6   call        _chkesp (00405178)
004030BB   mov         esp,ebp
004030BD   pop         ebp
004030BE   ret         4
004030C1   int         3
004030C2   int         3
004030C3   int         3
...
la lista riesco a scorrerla completamente con la funzione ::Stampa();
perciò mi fa pensare che la concatenazione funziona perfettamente,
un particolare che sento di dover aggiungere e che non ho mai
utilizzato fino a questo momento è l'allocazione dei template,
CElementoNext *esempio;
esempio = new CElementoNext<ELEMENTO>(); // allocare una classe
template
esempio = new CElementoNext();           // allocare una classe
normale
nel manuale "C++ la guida completa seconda edizione"
non avevo mai visto come allocare un template, perciò
ho provato delle soluzioni seguendo la logica del template,
non vorrei aver scritto qualcosa di sbagliato,
forse esiste un delete particolare?
speranzoso in una vostra risposta
bye duido

 
Ti sei assicurato che membro 'next' nell'ultimo nodo della lista sia 
effettivamente nullo? Se non l'hai inizializzato esplicitamente a 0, 
potrebbe contenere valori qualsiasi.
(Per inciso, non serve controllare che un puntatore non sia nullo prima di 
invocare 'delete'. 'delete' può essere benissimo invocato su puntatori 
nulli. In questi casi, non esegue alcuna operazione.)
Max

 forse esiste un delete particolare?
2) No. Non esiste un "delete" particolare. Quando usi "new" distruggi con
"delete" e quando usi "new[]" distruggi con "delete[]". Attenzione ai
puntatori a puntatore ( ma questo è un altro discorso ).
3) Per finire, ma più importante di tutto, credo fortemente che la logica
del tuo programma lasci a desiderare perchè non c'è motivo, o peggio è
deleterio, che sia la classe "CLista" come la classe "CElemLista" abbiano un
doppione di funzioni che fanno la stessa cosa.
Dovresti cercare di pensare in termini di oggetti:
L'oggetto CElemLista non ha alcuna cognizione di come è strutturata la lista
dentro la quale viene inserito.
Lo stesso ha solo un puntatore ad un'altro oggetto componente ma non può
sapere e non deve sapere in che ordine la lista viene acceduta per essere
visualizzata, oppure in quale modo sono concatenati gli elementi.
Se ogni nodo avesse un minimo di due puntatori a ad alri nodi, esso potrebbe
addirittura fare parte di un albero oltre che di una semplice lista che
contiene nodi che puntano a precedente o successivo nodo.
Pertanto è opportuno che la classe CElemLista si preoccupi solo di creare e
cancellare il nodo nella posizione fornita da funzioni della classe CLista.
Solo dentro quest'ultima saranno presenti le funzioni per la ricerca,
stampa, ordinamento, creazione e cancellazione della lista come oggetto
unitario.
Non ti invito a postare il sorgente così come si trova, ma eventualmente
solo dopo che lo avrai ripulito di tutto il superfluo, e avrai tenuto conto
di come si istanziano i template di classe e di funzione.
Buon lavoro,
FabioMDF
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

ti ringrazio molto, ho letto soltanto ora il post e adesso provo a
rivedermi il tutto,
questa soluzione ElemLista<ELEMENTO> *nodePtr = new
ElemLista<ELEMENTO>(value);
l'ho dovuta utilizzare per forza perchč il compilatore come dicevi
segnala l'errore,
ero dubbioso del suo utilizzo, per quel strano comportamento nel
delete...
nel frattempo ho cercato di capire meglio l'errore della lista,
ho reimplementato il codice con classi e ho lasciato da parte i
template, ma l'errore persiste,
senza impegno vorrei chiedere cortesemente se qualcuno puň provare il
codice, perchč non ne esco con niente,
compilato con MV,
basta compilarlo ed eseguirlo per visualizzare l'errore di Stack
Overflow quando dealloca la lista,
http://www.redangel.it/click_file.asp?m=1078&l=1
come dicevo, l'errore mi sembra molto strano perchč la lista funziona,
ma la deallocazione...
ringrazio anticipatamente chiunque voglia interessarsi alla questione
bye duido

Ciao,
ho scaricato il codice pensando di poterlo guardare stasera ma č tardissimo
e non so se potrň farlo neanche dopo perchč ho visto che č composto da molti
files.
C'č una cosa che perň mi sono dimenticato di dirti, mentre ero preso dalle
altre considerazioni.
Ho notato quel frammento di codice dove:
	if (lista) delete lista;
Non so che cosa stai cancellando, ma se "lista" č l'intera lista, con tutti
gli elementi (nodi) ancora presenti, stai sbagliando.
La memoria precedentemente riservata per ogni singolo elemento deve essere
rilasciata facendo la "delete" di ogni singolo nodo, tenedo conto di
aggiornare il puntatore all'inizio o alla fine della stessa lista e
eventualmente anche il puntatore a prossimo nodo presente nel nodo
precedente a quello cancellato.
Ma tutto questo dipende fortemente dall'architettura della lista e dai
metodi di rimozione (fromBack, fromHead, casuale, eccetera).
Vorrei anche consigliarti di imparare ad utilizzare un buon debugger ( io
uso GDB ) che, nei casi di stack overflow e altri tentativi vari di
corruzione di memoria, ti č utilissimo nel mostrarti i valori di tutte le
variabili che vuoi tenere sotto controllo, il tracciamento delle operazioni
sullo stack (backtracing) e molto altro.
A questo indirizzo c'č il miglior tutorial esistente ( e pure gratis ):
 
http://sources.redhat.com/gdb/current/onlinedocs/gdb.html
Ciao,
FabioMDF

--------------------------------
Inviato via 
http://arianna.libero.it/usenet/