Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  1. #1

    [C++] Polimorfismo e messaggi dalla memoria...

    Buongiorno a tutti.
    Ragazzi ho fatto un programma dove utilizzo sia il polimorfismo che la derivazione multipla. Il programma svolge il suo compito ma non so perchè dopo l'esecuzione mostra i seguenti messaggi nel terminale scritti in rosso (programmo sotto Ubuntu con Eclipse):

    codice:
    *** glibc detected *** /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione: free(): invalid pointer: 0xbfc5b604 ***
    ======= Backtrace: =========
    /lib/libc.so.6(+0x6c501)[0x17c501]
    /lib/libc.so.6(+0x6dd70)[0x17dd70]
    /lib/libc.so.6(cfree+0x6d)[0x180e5d]
    /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x3a5441]
    /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione[0x8048f18]
    /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione[0x80494ef]
    /lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
    /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione[0x8048881]
    ======= Memory map: ========
    00110000-00267000 r-xp 00000000 08:02 253474     /lib/libc-2.12.1.so
    00267000-00269000 r--p 00157000 08:02 253474     /lib/libc-2.12.1.so
    00269000-0026a000 rw-p 00159000 08:02 253474     /lib/libc-2.12.1.so
    0026a000-0026d000 rw-p 00000000 00:00 0 
    002fb000-003da000 r-xp 00000000 08:02 656528     /usr/lib/libstdc++.so.6.0.14
    003da000-003de000 r--p 000de000 08:02 656528     /usr/lib/libstdc++.so.6.0.14
    003de000-003df000 rw-p 000e2000 08:02 656528     /usr/lib/libstdc++.so.6.0.14
    003df000-003e6000 rw-p 00000000 00:00 0 
    005ee000-00612000 r-xp 00000000 08:02 253478     /lib/libm-2.12.1.so
    00612000-00613000 r--p 00023000 08:02 253478     /lib/libm-2.12.1.so
    00613000-00614000 rw-p 00024000 08:02 253478     /lib/libm-2.12.1.so
    00ca6000-00cc2000 r-xp 00000000 08:02 253471     /lib/ld-2.12.1.so
    00cc2000-00cc3000 r--p 0001b000 08:02 253471     /lib/ld-2.12.1.so
    00cc3000-00cc4000 rw-p 0001c000 08:02 253471     /lib/ld-2.12.1.so
    00eac000-00ec6000 r-xp 00000000 08:02 1316415    /lib/libgcc_s.so.1
    00ec6000-00ec7000 r--p 00019000 08:02 1316415    /lib/libgcc_s.so.1
    00ec7000-00ec8000 rw-p 0001a000 08:02 1316415    /lib/libgcc_s.so.1
    00f1f000-00f20000 r-xp 00000000 00:00 0          [vdso]
    08048000-0804b000 r-xp 00000000 08:02 1613514    /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione
    0804b000-0804c000 r--p 00002000 08:02 1613514    /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione
    0804c000-0804d000 rw-p 00003000 08:02 1613514    /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione
    08bf2000-08c13000 rw-p 00000000 00:00 0          [heap]
    b7600000-b7621000 rw-p 00000000 00:00 0 
    b7621000-b7700000 ---p 00000000 00:00 0 
    b77f3000-b77f6000 rw-p 00000000 00:00 0 
    b780c000-b7810000 rw-p 00000000 00:00 0 
    bfc3b000-bfc5c000 rw-p 00000000 00:00 0          [stack]
    Suppongo che dipenda da qualche problema con l'allocazione dinamica (leggo heap e stack) ma se cosi fosse il compilatore non mi direbbe nulla nel momento in cui "alloco male" un puntatore?
    Ovviamente non pretendo che vi mettiate a vedere tutto per filo e per segno ma magari siete già incappati in una situazione simile e potete indicarmi dove ho sbagliato.

    UN GRAZIE ANTICIPATO A CHI RISPONDE

    PS
    Qualcuno saprebbe spiegarmi anche come mai ogni volta che acquisisco una stringa utilizzando prima cin.ignore e poi cin.get finisce sempre per mangiarsi la prima lettera? Ad esempio inserisco PLUTO e lui legge LUTO...

    PPS
    Non so se poi è utile, comunque allego anche l'output del programma e le varie sezioni di codice (non badate alla logica del programma, era solo per esercitarmi )


    classe Animali (la classe base)
    codice:
    /*
     * animali.h
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #ifndef ANIMALI_H_
    #define ANIMALI_H_
    
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    typedef char * stringa;
    
    class Animali {
    
    	stringa nome;
    	float eta;
    
    public:
    	//costruttori
    	Animali(){nome=NULL;}
    	Animali (const float & e) {eta=e;}
    	Animali (const char N[]);
    	Animali(const char N[], const float & e );
    
    	//funzioni polimorfe per le derivate
    	virtual void verso (){}
    	virtual void cibo(){}
    	virtual void ChiSono() {}
    
    	//funzioni per età
    	void setEta(){cout << "\nInserire eta': "; cin >> eta;}
    	float getEta() {return eta;}
    
    	//funzioni per nome
    	void setNome(){char n[15];cout<<"\nInserire nome:  "; cin.ignore(); cin.get(n,14); nome=new char[strlen(n)+1];
    	strcpy(nome,n);}
    
    	stringa getNome(){return nome;}
    
    	//distruttore
    	virtual ~Animali() {delete nome;}
    };
    
    #endif /* ANIMALI_H_ */
    
    
    /*
     * animali.cpp
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #include "animali.h"
    
    Animali::Animali (const char N[]){
    
    	nome=new char[strlen(N)+1];
    	strcpy(nome,N);
    
    }
    
    Animali::Animali(const char N[], const float & e ){
    
    	nome=new char[strlen(N)+1];
    	strcpy(nome,N);
    
    	eta=e;
    
    }
    classe Cane (derivata di Animali)
    codice:
     /*
     * cane.h
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #ifndef CANE_H_
    #define CANE_H_
    
    #include "animali.h"
    
    class Cane: public virtual Animali {
    
    	stringa pelo;
    	stringa razza;
    
    public:
    	//Costruttori
    	Cane (const char N[],const float & eta, const char P[], const char R[]);
    	Cane (const char N[],const float & eta): Animali::Animali(N,eta) {}
    	Cane (const char P[]): Animali::Animali() { pelo=new char [strlen(P)+1]; strcpy(pelo,P);}
    
    	//ridefinizione delle funzioni virtuali
    	virtual void verso() {cout << "\nBAU! BAU!";}
    	virtual void cibo () {cout << "\nMangio di tutto!";}
    	virtual void ChiSono() {cout << "\nSono un cane!";}
    
    	//funzioni per pelo
    	void setPelo() {char Pelo[10]; cout<< "\nPelo: "; cin.ignore(); cin.get(Pelo, 9); pelo= new char [strlen(Pelo)+1];
    	strcpy(pelo, Pelo);}
    
    	stringa getPelo() {return pelo;}
    
    	//funzioni per razza
    	void setRazza();
    	stringa getRazza() {return razza;}
    
    	//distruttore
    	virtual ~Cane(){ delete pelo; delete razza;}
    
    
    
    };
    
    
    #endif /* CANE_H_ */
    
    
    
    /*
     * cane.cpp
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #include "cane.h"
    
    Cane::Cane (const char N[],const float & eta, const char P[], const char R[]): Animali::Animali(N,eta) {
    
    
    	razza= new char [strlen(R)+1];
    	strcpy(razza, R);
    
    	pelo= new char [strlen(P)+1];
    	strcpy(pelo, P);
    }
    
    
    void Cane::setRazza(){
    
    	char R[15];
    	cout << "\nRazza:";
    	cin.ignore();
    	cin.get(R,14);
    
    	razza= new char [strlen(R)+1];
    	strcpy(razza, R);
    
    }

    classe Lupo (altra derivata da Animali)
    codice:
    /*
     * lupo.h
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #ifndef LUPO_H_
    #define LUPO_H_
    
    #include "animali.h"
    
    class Lupo: public virtual Animali {
    
    public:
    	Lupo(const char N[], const float & e):Animali::Animali(N,e) {}
    
    	virtual void verso() {cout << "\nGRR! GRR!";}
    	virtual void cibo() {cout<<"\nPrediligo la carne fresca!";}
    	virtual void ChiSono() {cout << "\nSono un lupo!";}
    
    	virtual ~Lupo(){}
    
    };
    
    
    #endif /* LUPO_H_ */


    classe CaneLupo (derivata da Cane e Lupo)
    codice:
    /*
     * canelupo.h
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #ifndef CANELUPO_H_
    #define CANELUPO_H_
    
    #include "animali.h"
    #include "cane.h"
    #include "lupo.h"
    
    class CaneLupo: public Cane, public Lupo {
    
    public:
    
    	CaneLupo (const char N[], const float & e): Cane::Cane(N,e), Lupo::Lupo(N,e){}
    
    	virtual void verso() {Cane::verso(); Lupo::verso();}
    	virtual void cibo() {Cane::cibo(); cout<<"\n ed inoltre"; Lupo::cibo();}
    	virtual void ChiSono() {Cane::ChiSono(); cout << "\n ed inoltre"; Lupo::ChiSono();}
    
    	virtual ~CaneLupo() {}
    };
    
    #endif /* CANELUPO_H_ */
    MAIN
    codice:
     /*
     * main.cpp
     *
     *  Created on: 16/feb/2011
     *      Author: adrycast
     */
    
    #include "animali.h"
    #include "cane.h"
    #include "lupo.h"
    #include "canelupo.h"
    
    int main () {
    
    	char N[20];
    	float e;
    
    	//azioni preliminari (per i costruttori)
    	cout << "\nNome animale: ";
    	cin.ignore();
    	cin.get(N, 19);
    	cout << "\Eta' animale:  ";
    	cin >> e;
    
    	//inizializzo Classi
    	Animali a(N,e);
    	Cane c(N,e);
    	Lupo l(N,e);
    	CaneLupo cl(N,e);
    
    	cout << "\n****INIZIO****\n";
    	cout << "\n**CHIAMATE NORMALI!";
    
    	//su Animali
    	cout << "\neta' animale: "<<a.getEta();
    	cout << "\nnome animale: "<<a.getNome();
    	cout << "\n";
    
    	cout << "\nRICHIAMO CANE";
    	//su Cane
    	c.ChiSono();
    	c.setPelo();
    	cout << "\nHai scritto che il mio pelo è  "<<c.getPelo();
    	cout << "\n";
    	c.setRazza();
    	cout << "\nHai scritto che appartengo alla razza dei  "<<c.getRazza();
    	cout << "\n";
    	cout << "\nIl mio verso è  ";
    	c.verso();
    	cout << "  ed inolte  ";
    	c.cibo();
    	cout << "\n";
    
    	cout << "\nRICHIAMO LUPO";
    	//su Lupo
    	l.ChiSono();
    	cout << "\n";
    	cout << "\nIl mio verso è  ";
    	l.verso();
    	cout << "  ed inolte  ";
    	l.cibo();
    	cout << "\n";
    
    	cout << "\nRICHIAMO CANELUPO";
    	//su CaneLupo
    	cl.ChiSono();
    	cout << "\n";
    	cout << "\nIl mio verso è  ";
    	cl.verso();
    	cout << "  ed inolte  ";
    	cl.cibo();
    
    	cout << "\n****FINE PROG NORMALE****\n";
    	cout << "\n****INIZIO PROG CON PUNTATORI E BINDING DINAMICO****\n";
    
    	typedef Animali * A;
    
    	cout << "\n**Punto CANE da ANIMALI**";
    	A ptrc=&c;
    	ptrc->ChiSono();
    	cout << "\n";
    	ptrc->verso();
    	cout << "\n";
    	ptrc->cibo();
    	cout << "\n";
    
    	cout << "\n**Punto LUPO da ANIMALI**";
    	A ptrl=&l;
    	ptrl->ChiSono();
    	cout << "\n";
    	ptrl->verso();
    	cout << "\n";
    	ptrl->cibo();
    	cout << "\n";
    
    	cout << "\n**Punto CANELUPO da CANE**";
    	typedef Cane * C;
    	C ptrcl=&cl;
    	ptrcl->ChiSono();
    	cout << "\n";
    	ptrcl->verso();
    	cout << "\n";
    	ptrcl->cibo();
    	cout << "\n";
    
    
    	delete ptrc;
    	delete ptrl;
    	delete ptrcl;
    
    	a.~Animali();
    	c.~Cane();
    	l.~Lupo();
    	cl.~CaneLupo();
    
    	cout << "\n**********FINE**********\n";
    
    	return EXIT_SUCCESS;
    
    }
    Qui poi chiamo o non chiamo i distruttori e dealloco o non dealloco i puntatori al prog non fa nessuna differenza, ho sempre l'output di errore dal terminale.


    OUTPUT
    codice:
    Nome animale: PLUTO
    ta' animale:  8
    
    ****INIZIO****
    
    **CHIAMATE NORMALI!
    eta' animale: 8
    nome animale: LUTO
    
    RICHIAMO CANE
    Sono un cane!
    Pelo: corto
    
    Hai scritto che il mio pelo è  corto
    
    Razza:labrador
    
    Hai scritto che appartengo alla razza dei  labrador
    
    Il mio verso è  
    BAU! BAU!  ed inolte  
    Mangio di tutto!
    
    RICHIAMO LUPO
    Sono un lupo!
    
    Il mio verso è  
    GRR! GRR!  ed inolte  
    Prediligo la carne fresca!
    
    RICHIAMO CANELUPO
    Sono un cane!
     ed inoltre
    Sono un lupo!
    
    Il mio verso è  
    BAU! BAU!
    GRR! GRR!  ed inolte  
    Mangio di tutto!
     ed inoltre
    Prediligo la carne fresca!
    ****FINE PROG NORMALE****
    
    ****INIZIO PROG CON PUNTATORI E BINDING DINAMICO****
    
    **Punto CANE da ANIMALI**
    Sono un cane!
    
    BAU! BAU!
    
    Mangio di tutto!
    
    **Punto LUPO da ANIMALI**
    Sono un lupo!
    
    GRR! GRR!
    
    Prediligo la carne fresca!
    
    **Punto CANELUPO da CANE**
    Sono un cane!
     ed inoltre
    Sono un lupo!
    
    BAU! BAU!
    GRR! GRR!
    
    Mangio di tutto!
     ed inoltre
    Prediligo la carne fresca!
    Ovviamente seguito dall'errore scritto sopra.
    "Science is a differential equation.
    Religion is a boundary condition."
    (Alan Touring)

  2. #2
    L'errore dice
    codice:
    *** glibc detected *** /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione: free(): invalid pointer: 0xbfc5b604 ***
    Gia ti dovrebbe far pensare che non è che alloca male la memoria, ma la libera male, ed il perchè è evidente:

    Perchè chiami esplicitamente il distruttore ?
    Viene fatto implicitamente quando viene distrutto l'oggetto. Il problema è che crei degli oggetti sullo stack e poi li fai puntare da un reference.

    Fai delete sulle reference quindi il compilatore (non tutti) non vedono un errore, ma è sbagliato: prima li distruggi con delete, ma poi vengono distrutti a loro volta perchè sono statici, quindi di fatto richiami 2 volte i distruttori.

    Togli i delete e le chiamate ai distruttori perchè non servono. La memoria di quegli oggetti viene liberata perchè sono statici.

    PS: per il problema di cin prova a fare cin.flush prima di get
    lolide
    Java Programmer

    Informati

  3. #3
    Originariamente inviato da lolide
    L'errore dice
    codice:
    *** glibc detected *** /home/adrycast/workspace/animali_derivazione/Debug/animali_derivazione: free(): invalid pointer: 0xbfc5b604 ***
    Gia ti dovrebbe far pensare che non è che alloca male la memoria, ma la libera male, ed il perchè è evidente:

    Perchè chiami esplicitamente il distruttore ?
    Viene fatto implicitamente quando viene distrutto l'oggetto. Il problema è che crei degli oggetti sullo stack e poi li fai puntare da un reference.

    Fai delete sulle reference quindi il compilatore (non tutti) non vedono un errore, ma è sbagliato: prima li distruggi con delete, ma poi vengono distrutti a loro volta perchè sono statici, quindi di fatto richiami 2 volte i distruttori.

    Togli i delete e le chiamate ai distruttori perchè non servono. La memoria di quegli oggetti viene liberata perchè sono statici.

    PS: per il problema di cin prova a fare cin.flush prima di get
    Ciao
    grazie per la risposta (anche perchè forse ho scritto un post un pò troppo corposo )

    Purtroppo non è quello il problema.
    Infatti di solito non richiamo mai i distruttori, è un aggiunta che ho fatto in seguito alla prima esecuzione dove mi dava sempre gli stessi messaggi in output. Preso dall'idea della memoria ho pensato che per qualche strana ragione non mi deallocava bene gli spazi e cosi ho esplicitato le chiamate ma con o senza la "deallocazione esplicita" non mi cambia praticamente nulla
    "Science is a differential equation.
    Religion is a boundary condition."
    (Alan Touring)

  4. #4
    Originariamente inviato da adrycast
    Ciao
    grazie per la risposta (anche perchè forse ho scritto un post un pò troppo corposo )

    Purtroppo non è quello il problema.
    Infatti di solito non richiamo mai i distruttori, è un aggiunta che ho fatto in seguito alla prima esecuzione dove mi dava sempre gli stessi messaggi in output. Preso dall'idea della memoria ho pensato che per qualche strana ragione non mi deallocava bene gli spazi e cosi ho esplicitato le chiamate ma con o senza la "deallocazione esplicita" non mi cambia praticamente nulla
    Hai tolto anche i delete ?

    Questa parte:

    codice:
    	delete ptrc;
    	delete ptrl;
    	delete ptrcl;
    
    	a.~Animali();
    	c.~Cane();
    	l.~Lupo();
    	cl.~CaneLupo();
    deve sparire

    lolide
    Java Programmer

    Informati

  5. #5
    Originariamente inviato da lolide
    Hai tolto anche i delete ?

    Questa parte:

    codice:
    	delete ptrc;
    	delete ptrl;
    	delete ptrcl;
    
    	a.~Animali();
    	c.~Cane();
    	l.~Lupo();
    	cl.~CaneLupo();
    deve sparire

    No ma questa parte non c'era proprio all'inizio e l'ho introdotta proprio come "possibile soluzione" al problema ma non era proprio scritta ad una prima stesura del codice. Il programma è stato avviato sia CON che SENZA queste istruzioni e l'errore rimaneva lo stesso
    "Science is a differential equation.
    Religion is a boundary condition."
    (Alan Touring)

  6. #6
    Uhm.. sicuramente è un problema di disallocazione.
    Prova a fare un controllo se il puntatore dell'attributo che disallochi non sia 0, in ogni distruttore di ogni classe.

    Dovresti risolvere, ma si dovrebbe ancora capire qual'è il problema.
    Comunque se risolvi, il problema è che uno di quegli attributi non viene inizializzato, e quindi quando cerca di distruggerlo da errore.
    lolide
    Java Programmer

    Informati

  7. #7
    Originariamente inviato da lolide
    Uhm.. sicuramente è un problema di disallocazione.
    Prova a fare un controllo se il puntatore dell'attributo che disallochi non sia 0, in ogni distruttore di ogni classe.

    Dovresti risolvere, ma si dovrebbe ancora capire qual'è il problema.
    Comunque se risolvi, il problema è che uno di quegli attributi non viene inizializzato, e quindi quando cerca di distruggerlo da errore.
    Quindi dovrei mettere un controllo all'interno dei distruttori dici?
    Però sarebbe parecchio strano (o almeno a me mi flipperebbe un pò il cervello ) ...nel senso che l'esecuzione fa tutto come deve, sia la parte in cui utilizzo il binding statico che la parte in cui faccio il binding dinamico con in puntatori, se i puntatori agli oggetti non fossero inizializzati l'esecuzione da un punto di vista logico non ne risentirebbe?

    Comunque appena torno a casa (sto scendendo ora) provo a fare come hai detto e poi posto i risultati.

    Ti ringrazio molto per l'aiuto
    "Science is a differential equation.
    Religion is a boundary condition."
    (Alan Touring)

  8. #8
    Originariamente inviato da adrycast
    Quindi dovrei mettere un controllo all'interno dei distruttori dici?
    Però sarebbe parecchio strano (o almeno a me mi flipperebbe un pò il cervello ) ...nel senso che l'esecuzione fa tutto come deve, sia la parte in cui utilizzo il binding statico che la parte in cui faccio il binding dinamico con in puntatori, se i puntatori agli oggetti non fossero inizializzati l'esecuzione da un punto di vista logico non ne risentirebbe?

    Comunque appena torno a casa (sto scendendo ora) provo a fare come hai detto e poi posto i risultati.

    Ti ringrazio molto per l'aiuto
    Si hai ragione.
    Infatti è solo una prova: almeno sappiamo che qualche attributo della classe non viene allocato.

    Ho letto il codice e mi sembra apposto, anch'io non mi spiego quell'errore.
    Può anche darsi che non so quando allochi gli attributi, magari c'è qualche errore di memoria e non l'alloca.
    Cominciamo a scartare le possibilità

    PS: prova a correggere quel fatto di cin, magari è proprio quello. aggiungi cin.flush prima di get.
    lolide
    Java Programmer

    Informati

  9. #9
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    A parte le 3000 allocazioni inutili che fai, uno dei problemi è qui:
    codice:
    //distruttore
    	virtual ~Animali() {delete nome;}
    nome è un puntatore a una serie di char, non a un singolo char.
    La sintassi corretta è:
    codice:
    //distruttore
    	virtual ~Animali() {delete[] nome;}
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  10. #10
    Grazie per le risposte e per lo sbattone di leggervi i vari pezzi di codice ragazzi

    @shodan
    Guarda le 3000 allocazioni sono per esercizio, come ad esempio 4 costruttori fatti per la classe Animali e poi ne uso sempre solo uno. Semplicemente ho un esame e faccio 10000 cose futili ai fini logici ma utili per farmi prendere la mano ad allocare e deallocare (ed infatti dealloco praticamente tutto..)

    Comunque il problema non è neanche quello che dici tu. Ho messo le parentesi quadre sia nel distruttore da te evidenziato che negli altri distruttori che dovevano deallocare stringhe ma il problema resta lo stesso.

    @Iolide
    Come avevamo previsto il controllo sulle deallocazioni dei distruttori non dà problemi. Anche qui resta sempre il messaggio di invalid pointer..


    "Science is a differential equation.
    Religion is a boundary condition."
    (Alan Touring)

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.