Newsgroup: it.comp.lang.c++
Titolo: Errore nel costruttore/distruttore?

Credo di avere problemi con il costruttore di copia oppure con il 
distruttore di questa classe di vettori/matrici...
programmi che creano, distruggono oggetti, con funzioni che 
restituiscono farray mi vanno in segfault;
se elimino il distruttore i programmi funzionano bene solo che 
ovviamente sprecano memoria perchè non liberano mai la memoria allocata 
dagli array costruiti...
qualche suggerimento?
// -*-C++-*-
#include <cmath>
using std::sqrt;
namespace tonymatrix
{
   template <class T>
   class farray
   {
     T* v_;
     int dim_;
   public:
     explicit inline farray(): dim_(0), v_(0) {};
     explicit inline farray (int a): dim_(a) {v_= new T[dim_];}
     inline ~farray() {delete []v_;};
     inline farray  (const farray &b):dim_(b.size())  { v_= new T[dim_]; 
for (int i=0;i!=dim_;i++) v_[i]=b.v_[i]; }
     inline T& operator() (int i){return v_[i-1];}
     inline const  T& operator() (int i) const {return v_[i-1];}
     inline T& operator[] (int i){return v_[i-1];}
     inline const  T& operator[] (int i) const {return v_[i-1];}
     inline int dim() const {return dim_;}
     inline int dim1() const {return dim_;}
     inline int size() const{return dim_;}
     inline T sum() const {T res; for (int i=0;i!=dim_;i++) res+=v_[i]; 
return res;}
   };
   template <class T>
   class fmatrix {
     T* v_;
     int dim1_,dim2_;
   public:
     explicit fmatrix (int a,int b): dim1_(a), dim2_(b) {v_= new T[a*b]; }
     explicit inline fmatrix (const fmatrix &b): 
dim1_(b.dim_1),dim2_(b.dim2_) {int dim=dim1_*dim2;v_= new T[dim]; for 
(int i=0;i!=dim;i++) v_[i]=b.v_[i];}
     ~fmatrix() {delete []v_;}
     inline T& operator() (int i, int j){return v_[(i-1)*dim1_+j-1];}
     inline const  T& operator() (int i, int j) const {return 
v_[(i-1)*dim1_+j-1];}
     inline int dim1() const {return dim1_;}
     inline int dim2() const {return dim2_;}
     inline int size() const {return dim1_*dim2_;}
     inline T sum() const {T res; int dim=dim1_*dim2_; for (int 
i=0;i!=dim;i++) res+=v_[i]; return res;}
   };
   template <class T> inline T dot_product(const farray<T> &vec1, const 
farray<T> &vec2)
   {
     T res=0;
     int a=vec1.size(), b=vec2.size();
     if (a>b) a=b;
     for (int i=1;i<=a;i++)
       {
	res+=vec1[i]*vec2[i];
       }
     return res;
   }
   template <class T> inline   double norm(const farray<T> &vec1)
   {
     return sqrt((dot_product(vec1,vec1)));
   }
   template <class T> inline void normalize (farray<T> &vec)
   {
     int a=vec.size();
     double denom= norm(vec);
     if (denom!=0) for (int i=1;i<=a;i++) vec[i]/=denom;
   }
}
-- 
Hai recensioni nel cassetto di musica, cinema, letteratura,fumetti??
Ascolta e pentiti e se hai tempo vergognati
http://tonysuper.altervista.org

     inline const  T& operator[] (int i) const {return v_[i-1];}
Perche' sempre "i-1" invece di "i"?
Cmq, io ho provato a scrivere un po' di codice che passava farray avanti 
e indietro da funzioni, e non mi dava nessun problema. D'altronde, il 
codice mi pare corretto (non ho guardato quello di fmatrix).
-- 
Mat/tia Belletti - Undergraduate student @ 
cs.unibo.it
ICQ: 33292311    - email: 
mbel...@cs.unibo.it
IRC: RedGlow     - site(s): 
http://www.cs.unibo.it/~mbellett
Linux registered user 299762 @ Linux registered machine 213003

 
perchè partono da 1 gli indici farray sta per fortran array
se volete vi posto un lungo programma che con TNT (template numerical 
toolkit) funziona e con la mia classe no...


file tony.h
namespace tony{
   //fattoriale
inline unsigned long int fac(int num)
{
unsigned long int temp=1;
for (int i=1;i<=num;i++) temp*=i;
return temp;
}
//inutile non serve la libreria standard la fornisce
template<class T>
inline T min (T a, T b)
{
if (a<b) return a; else return b;
}
//inutile non serve la libreria standard la fornisce
template<class T>
inline T max (T a, T b)
{
if (a<b) return a; else return b;
}
//combinazioni ( a )  ottimizzata per usare il fattoriale solo al 
denominatore
//             ( b )
inline unsigned long int comb(int a, int b)
{
b=min(b,a-b);
unsigned long int dim=1;
for (int i=a;i>a-b;i--) dim*=i;
dim = dim/fac(b);
return dim;
}
//testa se un intero ha un bit acceso ... a Ãš il posto del bit, b Ãš 
l'intero...  dato l'inlineamento Ãš veloce
inline bool testbit (int a, unsigned long int b)// come sopra
{
return (b & (1<<a));
}
inline int sommabit (unsigned long int a)//dasostituire eventualmente 
con funzione pronta
{
int somma=0;
for (int i=1;i<=32;i++) if (testbit(i,a)) somma++;
return somma;
}
inline  int diff (unsigned long int i, unsigned long int j)
{
return (sommabit(i^j))/2;
}
}
file matrix.h
// -*-C++-*-
#include <cmath>
using std::sqrt;
namespace tonymatrix
{
   template <class T>
   class array
   {
     T* v_;
     int dim_;
   public:
     explicit inline array(): dim_(0), v_(0) {};
     explicit inline array (int a): dim_(a) {v_= new T[dim_];}
     inline ~array() {delete []v_;};
     inline array  (const array &b):dim_(b.size())  { v_= new T[dim_]; 
for (int i=0;i!=dim_;i++) v_[i]=b[i]; }
     inline T& operator() (int i){return v_[i];}
     inline const  T& operator() (int i) const {return v_[i];}
     inline T& operator[] (int i){return v_[i];}
     inline const  T& operator[] (int i) const {return v_[i];}
     inline int dim() const {return dim_;}
     inline int dim1() const {return dim_;}
     inline int size() const{return dim_;}
     inline T sum() const {T res; for (int i=0;i!=dim_;i++) res+=v_[i]; 
return res;}
   };
   template <class T>
   class matrix {
     T* v_;
     int dim1_,dim2_;
   public:
     explicit matrix (int a,int b): dim1_(a), dim2_(b) {v_= new T[a*b]; }
     explicit inline matrix (const matrix &b): 
dim1_(b.dim_1),dim2_(b.dim2_) {int dim=dim1_*dim2;v_= new T[dim]; for 
(int i=0;i!=dim;i++) v_[i]=b.v_[i];}
     ~matrix() {delete []v_;v_=0;}
     inline T& operator() (int i, int j){return v_[i*dim1_+j];}
     inline const  T& operator() (int i, int j) const {return 
v_[i*dim1_+j];}
     inline int dim1() const {return dim1_;}
     inline int dim2() const {return dim2_;}
     inline int size() const {return dim1_*dim2_;}
     inline T sum() const {T res; int dim=dim1_*dim2_; for (int 
i=0;i!=dim;i++) res+=v_[i]; return res;}
   };
   template <class T> inline T dot_product(const array<T> &vec1, const 
array<T> &vec2)
   {
     T res=0;
     int a=vec1.size(), b=vec2.size();
     if (a>b) a=b;
     for (int i=0;i!=a;i++)
       {
	res+=vec1[i]*vec2[i];
       }
     return res;
   }
   template <class T> inline   double norm(const array<T> &vec1)
   {
     return sqrt((dot_product(vec1,vec1)));
   }
   template <class T> inline void normalize (array<T> &vec)
   {
     int a=vec.size();
     double denom= norm(vec);
     if (denom!=0) for (int i=0;i!=a;i++) vec[i]/=denom;
   }
}
file: matlanczos.cpp
#include "matrix.h"
#include "fmatrix.h"
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include "tony.h"
#include <iomanip>
#include <vector>
using namespace std;
using namespace tonymatrix;
using namespace tony;
unsigned long int dimgiu,dimsu,dim;
unsigned int N,nsu,ngiu; int cicli;
float t,U;
vector<int> spaziosu, spaziogiu;
inline unsigned int statosu (unsigned int l) {return l/dimgiu;}
inline unsigned int statogiu (unsigned int l) {return l%dimgiu;}
inline int pow (int a, int b) {int res=1; for (int i=0;i<b;i++) res *= 
a; return res;}
template <class numero> farray <numero> Hamilt (const farray <numero> 
&vettore)
{
   int size=vettore.dim();
   farray <numero> result (size);
   for (int i=1;i<=size;i++) result(i)=0;
   for (int Hamilti=1;Hamilti<=dim;Hamilti++) {
     unsigned long int giui=spaziogiu[statogiu(Hamilti-1)];
     unsigned long int sui=spaziosu[statosu(Hamilti-1)];
 
result(Hamilti)=result(Hamilti)+U*(sommabit(sui&giui))*vettore(Hamilti);
     if (testbit(0,sui)&&(!(testbit(N-1,sui)))) 
result(mappa(sui-1+pow(2,N-1),giui)+1)=result(mappa(sui-1+pow(2,N-1),giui)+1) 
- t * vettore(Hamilti);
     if ((!testbit(0,sui))&&(testbit(N-1,sui))) 
result(mappa(sui+1-pow(2,N-1),giui)+1)=result(mappa(sui+1-pow(2,N-1),giui)+1) 
- t * vettore(Hamilti);
     for (int j=0;j<=N-2;j++) {
        if (testbit(j,sui)&&(!(testbit(j+1,sui)))) 
result(mappa(sui+pow(2,j),giui)+1)=result(mappa(sui+pow(2,j),giui)+1) -t 
* vettore(Hamilti);
        if ((!testbit(j,sui))&&(testbit(j+1,sui))) 
result(mappa(sui-pow(2,j),giui)+1)=result(mappa(sui-pow(2,j),giui)+1) -t 
* vettore(Hamilti);
     }
     if (testbit(0,giui)&&!(testbit(N-1,giui))) 
result(mappa(sui,giui-1+pow(2,N-1))+1)=result(mappa(sui,giui-1+pow(2,N-1))+1) 
-t * vettore(Hamilti);
     if (!testbit(0,giui)&&(testbit(N-1,giui))) 
result(mappa(sui,giui+1-pow(2,N-1))+1)=result(mappa(sui,giui+1-pow(2,N-1))+1) 
-t * vettore(Hamilti);
     for (int j=0;j<=N-2;j++) {
        if (testbit(j,giui)&&(!(testbit(j+1,giui)))) 
result(mappa(sui,giui+pow(2,j))+1)=result(mappa(sui,giui+pow(2,j))+1) -t 
* vettore(Hamilti);
        if ((!testbit(j,giui))&&(testbit(j+1,giui))) 
result(mappa(sui,giui-pow(2,j))+1)=result(mappa(sui,giui-pow(2,j))+1) -t 
* vettore(Hamilti);
     }
   }
   return result;
}
unsigned long int mappa (unsigned long int sui, unsigned long int giui)
{
   unsigned long int postosu, postogiu;
   for (int i=0;i<=dimsu-1;i++)
     if (spaziosu[i]==sui) {
       postosu=i;
       break;
     }
   for (int i=0;i<=dimgiu-1;i++)
     if (spaziogiu[i]==giui) {
       postogiu=i;
       break;
     }
   return (postosu*dimgiu+postogiu);
}
extern "C"
{
   void sstev_(char &job, int &n, float *d, float *e,  float *z, int 
&ldz, float *work,int &info);
}
int main()
{
   cin >> N >> nsu >> ngiu >> cicli >> t >> U;
   srand(time(NULL));
   dimsu= comb(N,nsu);
   dimgiu=comb(N,ngiu);
   dim=dimsu*dimgiu;
   cout << "Input : N=" << N<<" nsu="<< nsu<<" ngiu="<< ngiu<< " cicli=" 
<<cicli << " t=" <<t << " U=" <<U <<endl;
   spaziosu.resize(dimsu) , spaziogiu.resize(dimgiu);
   cout << "Generazione spazio di Hilbert"<<endl;
   int k=0;
   for (int i=0;i<pow(2,N)-1;i++)
     if (sommabit (i)==nsu) {
       spaziosu[k]=i;
       k++;
     }
   if (k!=dimsu) {cout<<"Errore grave nello spaziosu  " << k-1 << " " << 
dimsu; return(2);}
   k=0;
   for (int i=0;i<pow(2,N) -1;i++)
     if (sommabit (i)==ngiu) {
       spaziogiu[k]=i;
       k++;
     }
   if (k!=dimgiu) {cout<<"Errore grave nello spaziogiu  " << k-1 << " " 
<< dimgiu; return(2);}
   cout << "Dimensioni spazi" << endl<< setw(10) << dim 
<<setw(10)<<dimsu  <<setw(10) <<dimgiu<<endl;
   farray<float> trial(dim), vecuno(dim), vecdue (dim), prestep(dim), 
alfa(cicli), beta(cicli);
   cout << "Genero vettore random"<<endl;
   for (int i=1;i<=dim;i++) {trial(i)=float(rand())/(RAND_MAX+1);}
   normalize(trial);
   cout << "Genero secondo vettore" << endl;
   prestep=Hamilt(trial);
   cout << "Genero terzo vettore" << endl;
   alfa(1)=dot_product(trial,prestep);
   ofstream outalfa("alfa.txt"), outbeta("beta.txt");
   outalfa<<alfa(1)<<endl;
   for (int i=1;i<=dim;i++) vecuno(i)=prestep(i)-trial(i) *alfa(1);
   normalize(vecuno);
   beta(1)=dot_product(vecuno,prestep);
   outbeta << beta(1)<<endl;
   prestep=Hamilt(vecuno);
   alfa(2)=dot_product(vecdue,prestep);
   outalfa << alfa(2)<<endl;
   for (int i=1;i<=dim;i++) vecdue(i)=-vecuno(i)*alfa(2)-trial(i) 
*beta(1)+prestep(i);
   normalize(vecdue);
   beta(2)=dot_product(vecdue,prestep);
   outbeta<<beta(2)<<endl;
   for (int iteratore=3;iteratore<cicli;iteratore++) {
     for(int i=1;i<=dim;i++) trial(i)=vecuno(i);
     for(int i=1;i<=dim;i++) vecuno(i)=vecdue(i);
     prestep=Hamilt(vecuno);
     alfa(iteratore)=dot_product(vecuno,prestep);
     outalfa << alfa(iteratore)<<endl;
     for (int i=1;i<=dim;i++) vecdue(i)=prestep(i)-vecuno(i) 
*alfa(iteratore)-trial(i)*beta(iteratore-1);
     normalize(vecdue);
     beta(iteratore)=dot_product(vecdue,prestep);
     outbeta<<beta(iteratore) << endl;
     farray <float> su(iteratore), giu (iteratore);
     for (int i=1;i<=iteratore;i++) {su(i)=alfa(i);giu(i)=beta(i);}
     array <float> autovettori(iteratore*iteratore); farray <float> 
work(2*iteratore-2);
     int info; char mode='N';
 
sstev_(mode,iteratore,&su(1),&giu(1),&autovettori(0),cicli,&work(1),info);
     cout << " ciclo " << iteratore << " Energia parziale " <<su(1) << " 
  " << su(2) << "  " << su(3) << endl;
   }
   for(int i=1;i<=dim;i++) trial(i)=vecuno(i);
   for(int i=1;i<=dim;i++) vecuno(i)=vecdue(i);
   prestep=Hamilt(vecuno);
   alfa(cicli)=dot_product(vecuno,prestep);
   outalfa<< alfa(cicli)<<endl;
   cout<<"Diagonalizza"<<endl;
   array <float> autovettori(cicli*cicli); farray <float> work(2*cicli-2);
   int info; char mode='N';
   sstev_(mode,cicli,&alfa(1),&beta(1),&autovettori(0),cicli,&work(1),info);
   cout << "Diagonalizzazione finita con info " << info<<endl;
   cout << " Energia  " <<alfa(1) << "  " << alfa(2) << "  " << alfa(3) 
<< endl;
   fstream outval("autovalori.txt");
   for (int i=1;i<=cicli;i++) outval << setw(15) << alfa(i) << endl;


 ha scritto nel messaggio
news:2m495mF...@uni-berlin.de
..
Se tu fai:
farray array;   //chiamo il costruttore farray()
farray array2;     //chiamo il costruttore farray()
...
array = array2;    //chiamo l'operatore = non il costruttore di copia
...
delete array;
allora delete []v_ esegue la delete su un puntatore nullo.
nel distruttore fai qualcosa del genere:
inline ~farray() {if (v_ != 0) delete [] v_;};
Non so se questo risolve il tuo problema, ma sicuramente ne toglie di altri
potenziali.
Ciao
Andrea

 array = array2;    //chiamo l'operatore = non il costruttore di copia
io l'operatore = non l'ho definito e non lo uso
e nel programma non chiamo delete
se avessi voluto chiamare new e delete nei miei programmi avrei 
utilizzato gli array del c  e non una classe
comunque grazie


 ha scritto nel messaggio
news:cdit3r$vve$1...@admin.servernet...
Scusa, per la precisione, dimenticavo:
inline ~farray() {if (v_ != 0) {delete [] v_; v_= 0; }};

 
anche se aggiungo il bound checking con assert non cambia nulla...
non è un problema di limiti valicati


 allocata dagli array costruiti...
Manca l'operatore di assegnamento. 
Dopo
 
  farray x;
  farray y;
  ...
  x = y;
x.v_ e y._v_ puntato allo stesso array, che verra` distrutto 2 volte
dai distruttori di x e y.
        Mauro

 inline ~farray() {if (v_ != 0) delete [] v_;};
Completamente inutile, delete su un puntatore nullo e` innocua e non
esegue nessuna operazione.
        Mauro

 writes:

Ancora piu` inutile. v_ e` un membro di farray e verra` distrutto alla
fine del distruttore, cioe` subito dopo l'assegnamento.
        Mauro

 puntatore, che ormai non e` piu` valido.
Si può essere, ma mi sembra che tonysuper ha detto che l'operatore = non
viene mai chiamato, quindi non so se il problema è questo.

 io l'operatore = non l'ho definito e non lo uso
Invece lo usi (matlanczos.cpp):
  farray<float> trial(dim), vecuno(dim), vecdue (dim), prestep(dim),
    alfa(cicli), beta(cicli);
  ...          
  cout << "Genero secondo vettore" << endl;
  prestep=Hamilt(trial);      // <-----------
  ...   
  prestep=Hamilt(vecuno);     // <-----------
Se non hai intenzione di usare l'operatore =, e quello di default non
funziona, ti conviene dichiararlo privato e non implementarlo:
  private:
    farray& operator = (const farray&);
In questo modo se tenti di usarlo, il compilatore invece di generare
automaticamente un operatore non funzionante, segnala un errore.
        Mauro

 Invece lo usi (matlanczos.cpp):
infatti ho risolto implementando l'operatore =
grazie a tutti :-D


cosi' il programma funziona:
qualche suggerimento per aumentare l'efficienza degli operatori?
   template <class T>
   class farray
   {
     T* v_;
     int dim_;
   public:
     explicit inline farray(): dim_(0), v_(0) {};
     explicit inline farray (int a): dim_(a) {v_= new T[dim_];}
     inline ~farray() {delete [] v_; v_= 0; };
     inline farray  (const farray &b):dim_(b.size())  { v_= new T[dim_]; 
for (int i=0;i!=dim_;i++) v_[i]=b.v_[i]; }
     inline  farray operator=(const farray&b)
     {
       if (v_!=0) {
	delete [] v_;
	v_=0;
       }
	dim_=b.dim_;
	v_=new T[dim_];
	for (int i=0;i!=dim_;i++) v_[i]=b.v_[i];
		return *this;
     }
     inline T& operator() (int i){assert(i<=dim_&&i>0); return v_[i-1];}
     inline const  T& operator() (int i) const 
{assert(i<=dim_&&i>0);return v_[i-1];}
     inline T& operator[] (int i){assert(i<=dim_&&i>0);return v_[i-1];}
     inline const  T& operator[] (int i) const 
{assert(i<=dim_&&i>0);return v_[i-1];}
     inline int dim() const {return dim_;}
     inline int dim1() const {return dim_;}
     inline int size() const{return dim_;}
     inline T sum() const {T res; for (int i=0;i!=dim_;i++) res+=v_[i]; 
return res;}
   };


    };
CIAO, spero fosse solo un errore nel copia e incolla.
LMS

 LMS
adesso ho risolto in maniera molto piu' semplice
ho definito delle classi derivate di valarray a cui ho aggiunto 
semplicemente l'operatore () per gli indici...
tutto funziona bene perchè tutte le funzioni ereditate si comportano bene
#include <valarray>
using std::valarray;
namespace tonymatrix
{
   template <class T>
   class matrix : public valarray<T>{
       int dim1_,dim2_;
   public:
     explicit matrix (const int a,const int b):valarray<T>(a*b), 
dim1_(a), dim2_(b) {}
     matrix (const T &c,const int a,const int b):valarray<T>(c,a*b), 
dim1_(a), dim2_(b) {}
     inline T& operator() (const int i,const  int j){return 
operator[](i*dim2_+j);}
     inline const  T& operator() (const int i,const int j) const {return 
operator[](i*dim2_+j);}
     inline int dim1() const {return dim1_;}
     inline int dim2() const {return dim2_;}
     inline void set(const T  &c){int a=size();for (int i=0;i<a;i++) 
operator[](i)=c;}
     inline void apply( T func(T)){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func(operator[](i));}
     inline void apply( T func()){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func();}
    };
   template <class T>
   class array : public valarray<T>{
    public:
     explicit array (const int a): valarray <T> (a) {}
     array (const T &c,const int a): valarray <T> (c,a) {}
     inline const  T& operator() (const int i) const {return 
operator[](i);}
     inline   T& operator() (const int i)  {return operator[](i);}
     inline void set(const T & c){int a=size();for (int i=0;i<a;i++) 
operator[](i)=c;}
     inline void apply( T func(T)){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func(operator[](i));}
     inline void apply( T func()){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func();}
   };
   template <class T>
   class fmatrix : public valarray<T>{
       int dim1_,dim2_;
   public:
     explicit fmatrix (const int a,const int b):valarray<T>(a*b), 
dim1_(a), dim2_(b) {}
     fmatrix (const T &c,const int a,const int b):valarray<T>(c,a*b), 
dim1_(a), dim2_(b) {}
     inline T& operator() (const int i,const  int j){return 
operator[](j*dim1_+i-1-dim1_);}
     inline const  T& operator() (const int i,const  int j) const 
{return operator[](j*dim1_+i-1-dim1_);}
     inline int dim1() const {return dim1_;}
     inline int dim2() const {return dim2_;}
     inline void set(const T & c){int a=size();for (int i=0;i<a;i++) 
operator[](i)=c;}
     inline void apply( T func(T)){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func(operator[](i));}
     inline void apply( T func()){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func();}
  };
   template <class T>
   class farray : public valarray<T>{
    public:
     explicit farray (const int a): valarray <T> (a) {}
     farray (const T &c,const int a): valarray <T> (c,a) {}
     inline   T& operator() (const int i)  {return operator[](i-1);}
     inline const  T& operator() (const int i) const {return 
operator[](i-1);}
     inline void set(const T & c){int a=size();for (int i=0;i<a;i++) 
operator[](i)=c;}
     inline void apply( T func(T)){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func(operator[](i));}
     inline void apply( T func()){int a=size();for (int i=0;i<a;i++) 
operator[](i)=func();}
   };
template <class T> inline T dot_product (const valarray <T> &vec1,const 
valarray <T> &vec2)
{
   T res=0;
   int dim=vec1.size();
   for (int i=0;i<dim;i++) res+=vec1[i]*vec2[i];
   return res;
}
   template <class T> inline   double norm(const valarray<T> &vec1)
   {
     return sqrt((dot_product(vec1,vec1)));
   }
   template <class T> inline void normalize (valarray<T> &vec)
   {
     double denom= norm(vec);
     if (denom!=0) vec/=denom;
