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.