Newsgroup: it.comp.lang.c++
Titolo: Problema elementare di allocazione

Segmentation fault (core dumped)
Che significa?
Ho il sospetto che sia l'intero approccio ad essere sbagliato.
Ciao, Marvin
NB: uso Cygnus per win32
//-----Pippo.h
class Pippo{
public: 
	// array di interi
	int* vett;  
	// dimensione dell'array
	int n;      
	// costruttore e distruttore	
	Pippo( int );  
	~Pippo(){ delete [] vett; }
	// restituisce una nuova istanza di Pippo con gli 
	// elementi raddoppiati
	Pippo& raddoppia();    
 
	void stampa();
};
//-----fine Pippo.h
//-----Pippo.cpp
#include <stdio.h> 
#include "pippo.h" 
Pippo::Pippo( int dim ){
	n = dim;
	vett = new int[n];
	//pone tutti gli elementi di vett uguali a uno
	for( int i=0; i<n; i++ )	
		vett[i] = 1;
}
// crea e restituisce una nuova istanza di Pippo con gli elementi 
// raddoppiati
Pippo& Pippo::raddoppia(){
	static Pippo X( n );
	for( int i=0; i<n; ++i )
		X.vett[i] = 2*vett[i];
	return X;
}
void Pippo::stampa(){
	for( int i=0; i<n; ++i )
		printf("%d ", vett[i] );
	printf( "\n" );
}
//----fine Pippo.cpp
//----prova.cpp
#include "pippo.h"
main(){		
	Pippo A( 5 );
	Pippo B = A.raddoppia();
	A.stampa();
	B.stampa();	
}
//----fine prova.cpp
//----Makefile
CC = gcc
CFLAGS = -g
OBJS = pippo.o prova.o
prova : $(OBJS)
	$(CC) -o $@ $(OBJS) 
 
prova.o : pippo.h
pippo.o : pippo.h
//----fine Makefile

Quando, in Java, usi una classe č come se usassi un puntatore alla classe.
Per avere:
<JAVA>
Ciao crea()
{
    Ciao x = new Ciao;
    x.setup();
    return x;
}
</JAVA>
Devi fare:
<C++>
Ciao* crea()
{
    Ciao* x = new Ciao;
    x->setup();
    return x;
}
(e da qualche altra parte delete x)
</C++>
L'uso "diretto" degli oggetti, che vengono messi in stack e non nell'heap, č
un pň complicato se li devi passare by reference o averli come valori di
ritorno. Mentre in Java č facilissimo, ti sembra di passare loro ma passi
semplicemente i puntatori. Cosě sono capaci tutti :-)
--
Stefano Pettini
Notary of 
www.thawte.com

 (e da qualche altra parte delete x)
o ancora meglio, usare auto_ptr<Ciao>...

 snip
Ciao Marvin,
il tuo segmentation fault nasce dal fatto in cui tu stai assegnando a B il
ritorno di raddoppia():
Pippo B = A.raddoppia();
che e´ un oggetto statico, per cui alla fine del programma, quando A dovra´
essere distrutta, la X statica verra´ distrutta anche essa con A, ma cosa
succede a B?
Anche B deve essere distrutta, ma a B avevi passato l´indirizzo di X che era
gia´ stata distrutta, per cui stai usando una seconda volta il distruttore
sul vettore vett gia´ distrutto con conseguente disastro.
Il consiglio di usare gli autopointers e´ buono secondo me.
Oppure devi implementare con attenzione l´operatore di assegnamento e fare
attenzione a chiamare la delete di vett solo una volta.
Mauro

Prima di tutto ringrazio Stefano, Super e Mauro per le utilissime
risposte.
Non sospettavo neppure l'esistenza della classe auto_ptr (a scuola
avevo studiato il c++ sul libro di Stroustrup del 1986, e mi sono
accorto che da allora sono cambiate parecchie cose -- i template, per
dirne una).
Comunque: ho riscritto il mio programma di esempio, usando un
auto_ptr<Pippo> invece di una reference (le modifiche al sorgente sono
in coda al messaggio), e tutto sembra funzionare correttamente.
Dico "sembra" perche` faccio ancora fatica a capire quando e se un
oggetto deve essere cancellato esplicitamente dalla memoria libera (a
proposito, se qualcuno avesse la pazienza di spiegarmi la differenza
tra stack e heap...). Quando l'auto_ptr B va fuori scope, viene
invocato il distruttore della classe a cui punta, vero?
Inoltre: se un oggetto venisse "dimenticato", la memoria non verrebbe
liberata nemmeno all'uscita del programma? (Questo mi inquieterebbe
non poco, visto che la macchina non e` mia e non viene quasi mai
spenta.)
Infine, un altro piccolo problema: non riesco a usare gli stream.
(Infatti finora ho dovuto usare printf...)
Il programma:
   #include <iostream>
   main(){cout << "Ciao\n";}
non compila, ma ottengo:
  undefined reference to `cout'
  undefined reference to `ostream::operator<<(char const *)'
Ciao, Marvin
//----in pippo.cpp
auto_ptr<Pippo> Pippo::raddoppia(){
	auto_ptr<Pippo> X( new Pippo(n) );
	// ...
	return X;
}
//----in prova.cpp
main(){		
	Pippo A( 5 );
	auto_ptr<Pippo> B = A.raddoppia();
	A.stampa();
	B->stampa();	
}

  undefined reference to `ostream::operator<<(char const *)'
Ho appena scoperto che con g++ funziona correttamente (prima usavo
gcc). 
Pero` non so perche`.
-- 
Ciao, Marvin

 Pero` non so perche`.
Perché g++ č il compilatore C++ che dovevi usare fin dall'inizio, gcc č 
quello C quindi č normale che non compilasse, dato che il tuo codice č C++
Ciao
-- 
Luigi
--
bug windows [5] = {"95", "98", "NT", "Me", "2000"};

 quello C quindi č normale che non compilasse, dato che il tuo codice č C++
Tanto per la precisione, chiamando gcc ed utilizzando l'estensione .CC
per il sorgente, il compilatore chiama automaticamente g++ (questo
almeno succede con il porting DJGPP).
EMG

spenta.)
lo standard non garantisce nulla, cmq su un sistema operativo degno di
tal nome (i vari *nix) la memoria viene liberata quando termina il
processo. Se esegui il tuo prog su dei giocattoli (Win95?) non la
liberano.
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

liberano.
Non esageriamo... anche su 95 la memoria viene liberata (se
con questo intendi il risultato di allocazioni "normali" con
operator new).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 quello C quindi č normale che non compilasse, dato che il tuo codice č C++
gcc e g++ sono _front-end_ al preprocessore cpp, e ai compilatori cc1,
cc1obj, cc1plus, ecc. Non fanno altro che chiamarli con i comandi e
librerie corretti.
--
Bye,
  Mirko

operator new).
mea culpa, evidentemente avevo informazioni sbagliate.
