Newsgroup: it.comp.lang.c++
Titolo: Problema a run-time...

Salve a tutti,
ottengo un Segmentation fault e non capisco perchč.
Ho controllato con gdb, l'errore di presenta nell' fclose di
File::~File()
{
       if (file)
               std::fclose(file);
       if (fn_in)
               delete[] fn_in;
}
nel file File.cpp.
Errore:
----------
(gdb) #0 0x00000000 in ?? ()
(gdb) #1 0x400e710d in fclose@@GLIBC_2.1 () from /lib/libc.so.6
(gdb) #2 0x0804b86a in File::~File (this=0x8072c18, __in_chrg=0) at
../File.cpp:26
(gdb) #3 0x0805bca2 in AsciiFile::~AsciiFile (this=0x8072c18, __in_chrg=3)
(gdb) at ../AsciiFile.h:19
----------------------------------------
Non capisco il problema dove sta, visto che controllo in maniera
esplicita che non sia NULL.
Ecco il frammento completo (comrpeso costruttore):
-------------------------
File::File(const char* filename, bool ld)
{
	fn_in = new char[strlen(filename)+1];
	std::strcpy(fn_in,filename);
 
	load = ld;
	maxcnt = isetsz = 0;
	curr = reccnt = 0;
// bufsid = -1;
}
File::~File()
{
	if (file)
		std::fclose(file);
	if (fn_in)
		delete[] fn_in;
}
------------------------------------------
Non va neanche inserendo file = fopen(filename, "rb"); dopo
std::strcpy(fn_in,filename);.
Proposte?
Grazie 1000,
V.B.
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 }
a parte il fatto che sarebbe bene postare pezzi di codice compilabili e 
che riproducano il problema, in quello che hai scritto non c'č nulla che 
non vada. L'unica cosa che mi viene in mente: hai provato a verificare 
che, in quel contesto, this sia un puntatore valido? non č che File sia 
una classe facente parte di una gerarchia (i.e.: File deriva da 
qualcos'altro?)?
-- 
"Infilarti le piume in culo non fa di te una gallina!"

 esplicita che non sia NULL.
Immagino che "file" sia inizializzato nel costruttore; visto che
corrisponde ad una risorsa unica, sei sicuro di avere incluso nel copy
constructor e nell'assignment operator il codice per gestire
correttamente quella variabile?  Altrimenti la prima istanza
temporanea di un File che venga generata e poi distrutta ti chiude il
file, ed una seconda chiamata a fclose sullo stesso FILE * fa
esplodere il tutto.
P.S.: perche' usi le librerie di I/O del C e non quelle del C++ ?
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy              ROT13: 
ybe...@cq.vasa.vg

Quindi liberare due volte la stessa area di memoria fa saltare tutto?
Da notare che la versione Win32 funziona benissimo con lo stesso codice...
V.B.
 



Va "benissimo"? Il problema e' che fai una cosa sbagliata, ed il tuo
programma potrebbe smettere improvvisamente di funzionare in un momento
imprecisato. Molto meglio che scoppi immediatamente, secondo me.
Ciao,
Nicola

 Quindi liberare due volte la stessa area di memoria fa saltare tutto?
Chiamare fclose non 'libera memoria', chiude un file.  Se, dopo,
utilizzi il FILE * come se il file in questione fosse ancora aperto
pensi che sia una buona cosa?
Cfr. ISO/IEC 9899:1999 
7.19.3.4
: "The value of a pointer to a FILE
object is indeterminate after the associated file is closed (including
the standard text streams).".
Incidentalmente, "liberare due volte la stessa area di memoria" (ad
esempio chiamare operator delete due volte con lo stesso argomento)
causa undefined behavior (ISO/IEC 14882:1998 3.7.3.4); quindi e' assai
verosimile che faccia saltare tutto...


Ciao,
ancora non ho trovato il problema, vi posto i file .cpp e .h:
File.cpp:
----------------------
#pragma warning (disable: 4786)
#include <cstring>
#include <cstdlib>
#include <cassert>
#include "File.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
File::File(const char* filename, bool ld)
{
	fn_in = new char[strlen(filename)+1];
	std::strcpy(fn_in,filename);
	load = ld;
	maxcnt = isetsz = 0;
	curr = reccnt = 0;
// bufsid = -1;
}
File::~File()
{
	if (file)
		std::fclose(file);
	if (fn_in)
		delete[] fn_in;
}
bool File::read(ITEMSET& s)
{
	if (curr == isetsz) { /* if all records read */
		curr = 0; /* reset position of current pointer */
		if (!load) /* if to work on input file */
			if(!std::fseek(file, pos, SEEK_SET))
				error(E_FREAD,fn_in); /* reset file position */
		return false; /* return no file read */
	}
	if (load) /* if to work on memory */
		cis = isets[curr]; /* get current itemset */
	else
		get_iset(); /* otherwhise read from file */
	curr++; /* and increment the counter */
 
	s = cis; /* return s */
	return true;
}
ITEMSET* File::read()
{
	if (curr == isetsz) { /* if all records read */
		curr = 0; /* reset position of current pointer */
		if (!load) /* if to work on input file */
			if(std::fseek(file, pos, SEEK_SET) != 0)
				error(E_FREAD,fn_in); /* reset file position */
			return NULL; /* return no file read */
	}
 
	if (load) /* if to work on memory */
		cis = isets[curr]; /* get current itemset */
	else {
		get_iset(); /* otherwhise read from file */
		cis.prepare(); /* sort and remove duplicates */
	}
	curr++; /* and increment the counter */
 
	return &cis; /* return s */
 
}
int File::reorg(long thresh)
{
	SymTab tmap; /* temporary symbol table */
	int i, size;
	ITEM* item;
	std::vector<ITEM*> sorted = nimap.bvec; /* bucket vector */
	std::sort(sorted.begin(),sorted.end(),frqcmp()); /* order by frequency */
	for (i = 0, size = sorted.size();
	(i < size) && (sorted[i]->frq >= thresh); i++)
	{
		item = (ITEM*)tmap.insert(nimap.ids[sorted[i]->id], sizeof(ITEM));
		if (!item)
			return E_NOMEM; /* add the new item to the map, */
		item->frq = sorted[i]->frq;
	}
	nimap = tmap;
	return 0;
}
int File::reset()
{ /* resets to the beginning */
	if (load) /* if to work on memory */
		curr = 0; /* set the current pointer to 0 */
	else {
		if(std::fseek(file, pos, SEEK_SET) != 0) /* otherwise reset the file pointer
*/
			error(E_FREAD,fn_in); /* checking for I/O errors */
	}
	return 0; /* return OK */
}
ITEMSET* File::read(long i)
{ /* read i-th record */
		if (i < isetsz) { /* if current record exist */
			if (!load){ /* if to work on input file */
				int locpos = ftell(file); /* get the local record position */
				if(std::fseek(file, pos, SEEK_SET) != 0) /* set the file pointer */
					error(E_FREAD,fn_in); /* checking for I/O errors */
				long cnt = 0; /* get the local record counter */
				while(read()&&(++pos<i)); /* read records in sequence until ith */
				if(fseek(file, locpos, SEEK_SET) != 0) /* reset the file pointer */
					error(E_FREAD,fn_in); /* checking for I/O errors */
			}
			else cis = isets[i];
			return &cis; /* return s */
		}
		else return NULL; /* return no file read */
}
bool File::load_iset(int i, ITEMSET &trans)
{
	if (i < isetsz) { /* if current record exist */
		if (!load){ /* if to work on input file */
			int locpos = ftell(file); /* get the local record position */
			if(std::fseek(file, pos, SEEK_SET) != 0) /* set the file pointer */
				error(E_FREAD,fn_in); /* checking for I/O errors */
			long cnt = 0; /* get the local record counter */
			while(read()&&(++pos<i)); /* read records in sequence until ith */
			if(std::fseek(file, locpos, SEEK_SET) != 0) /* reset the file pointer */
				error(E_FREAD,fn_in); /* checking for I/O errors */
		} else
			trans = isets[i];
		return true; /* return s */
	} else
		return false; /* return no file read */
 
	trans=isets[i];
}
char* File::readTrans(int trans)
{
	int l = 0;
       int i;
	for (i = 0; i < isets[trans].size(); i++) {
		l += std::strlen(lookup(isets[trans][i]->id)) + 1;
	}
	char* result = new char[l + 1];
	strcpy(result,"");
	for (i = 0; i < isets[trans].size(); i++) {
		std::strcat(result,lookup(isets[trans][i]->id));
		std::strcat(result," ");
	}
	//fn_in = new char[strlen(filename)+1];
	//strcpy(fn_in,filename);
	return result;
}
----------------------
Ecco il file.h:
------------------------------------
#ifndef FILE_HPP_INCLUDED
#define FILE_HPP_INCLUDED
#include <vector>
#include "resources.h"
#include "Ctfscan.h"
#include "SymTab.h"
#define BUFSIZE 256 /* size of read buffer */
class File
{
public:
    char* readTrans(int trans);
	ITEMSET* read(long i);
	int reset();
	bool loaded() const;
	int items();
	hash_map<int, int> classcount;
	hash_map<std::string, int, hashString, eqstr> classes; /* Transaction-class
mapping */
	ITEMSET* read();
	SymTab& symbols();
	void insert_iset(ITEMSET is){isets.push_back(is);};
	bool load_iset(int i, ITEMSET &trans);
	const char* lookup(int id) const;
	const char* looktr(int id) const;
	int reorg(long thresh);
	int size() const;
	bool read(ITEMSET& s); /* read an itemset from buffer */
	File(const char* fname, /* file name */
		bool load = true /* flag for loading item sets */
);
	virtual ~File();
protected:
	FILE* file; /* file pointer */
	SymTab nimap; /* name/identifier map */
	SymTab trmap; /* Transaction map */
private:
	virtual void read_blk() = 0; /* caches the dataset into memory */
	virtual int get_item () = 0; /* --- read an item */
	virtual int get_iset () = 0; /* --- read an item set */
// void prepare (); /* --- sort set and remove duplicates */
protected:
	std::vector<ITEMSET> isets; /* item set vector */
	int isetsz; /* number of itemsets */
	ITEMSET cis; /* current item set */
	int reccnt; /* number of records read */
	bool load; /* flag for file-buffering */
	int maxcnt; /* maximal number of items per set */
	int curr; /* current record read */
	int pos; /* starting reading position in file */
	char* fn_in; /* file name */
};
inline int File::items()
{
	return nimap.size();
}
inline bool File::loaded()
const{
	return load;
}
inline int File::size() const{ /* get the number of itemset */
	return isetsz; /* currently loaded */
}
inline const char* File::lookup(int id) /* get the name of a given
identifier*/
const{
	return nimap.lookup(id);
}
inline const char* File::looktr(int id) /* get the name of a given
transaction*/
const{
	return trmap.lookup(id);
}
inline SymTab& File::symbols() /* gets the symbol table */
{
	return nimap;
}
#endif
--------------------------------------
Vi ricordo che il problema č nella sezione
File::~File()
{
	if (file)
		std::fclose(file);
	if (fn_in)
		delete[] fn_in;
}
in pratica segmentation fault quando viene fatto std::fclose(file);...e non
capisco perchč.
Vi ricordo inoltre che si tratta di un porting da una versione Win32, lě
nessun problema.
Grazie a tutti,
V.B.
 



 ancora non ho trovato il problema, vi posto i file .cpp e .h:
dovresti anche aggiungere una funzione main che riproduca il problema, 
se vuoi che ti si possa aiutare. Ma la fopen dove la fai?


 V.B.
Prova a mettere, nella sezione privata della classe File, nel .h
 private:
  File(const File&);
  File& operator=(const File&);
(senza implementarli)
Se il linker protesta significa che da qualche parte degli
oggetti File vengono copiati (cosa che non dovrebbe succedere,
altrimenti le due copie condividerebbero lo stesso puntatore:
la prima lo chiude correttamente e la seconda bomba).
Se non e' questo, potrebbe trattarsi di una classe derivata (visto che File
e' astratta) che magari chiude il file (che e' un membro protetto) nel
suo distruttore (che viene chiamato prima di quello della classe base).
-- Fabio