ein absolut "kranker" fehler
-
Wieder was gelernt, ich dachte immer, read würde beim ersten Parameter alles hinkopieren, dabei liefert read ja nur einen Zeiger auf den Speicher. ^^
Jedenfalls wäre dein Code dann korrekt
...
-
nene ganz so einfach ist das nicht...
ehrlich gesagt wusste ich nich genau, wie ich die sache mit read sonst hätte machen sollen..man liefert read im ersten parameter eine referenz auf einen pointer(oder einer als pointer getarnte variable) und eine byteangabe.
dann werden einfach soviele bytes wie angegeben hintereinander von der position des pointers an in den speicher kopiert.
die methode müsste eigentlich ganz gut funktionieren...
-
Fände es nicht schlecht, wenn du für das char-Array Speicher anlegen würdest.
Dann hätte der darein kopierte Speicher legalen Platz...
-
ok, hab nun den platz legalisiert
viel gebracht hats leider nicht, nun erscheint erst ne ca 1/4 seite lange leere in der console, dann kommt ne 1/4 seite text,zuerst wieder ein kauderwelsch, dann ist ein richtig lesbarer teil dabei, und es ist auch der text den ich wollte,dann kommt wieder zeichenkauderwelsch und dann kommt wieder bis zum schluss schwärze..ich glaub ich sollte langsam mal die read/open funktion posten oder? sonst bringt das nix
-
Ja, walte deines Amtes.
-
read funktion:
result Virtualfile::read(char* &buffer,unsigned int bytes){ if(datapointer!=NULL){ if(position+bytes<size){ for(unsigned int i=0;i<bytes;++i){ buffer[i]=readpointer[position+i]; } position+=bytes; return ok; } return out_of_range; } return stream_not_open; }
open funktion
result Virtualfile::open(char* Name){ if(datapointer==NULL){ ifstream Data(Name); if(Data.is_open()){ Data.seekg(0,ios::end); size=Data.tellg(); Data.seekg(0,ios::beg); datapointer=malloc(size); if(datapointer!=NULL){ readpointer=(char*)(datapointer); position=0; name=Name; char Buffer; for(unsigned int i=0;i<size;++i){ Data.read(&Buffer,sizeof(char)); readpointer[i]=Buffer; } Data.close(); return ok; } size=0; Data.close(); return failed; } return wrong_arguments; } return stream_allready_open; }
-
//result? benutz lieber exceptions result Virtualfile::read(char* &buffer,unsigned int bytes){ if(datapointer!=NULL){ //wozu? einfach den ctor die oeffnen //ueberlassen, dann brauchst du den kaese nicht //und selbst wenn, dann mach doch bitte //if(!datapointer) return stream_not_open; //bzw. natuerlich exception. if(position+bytes<size){ for(unsigned int i=0;i<bytes;++i){ buffer[i]=readpointer[position+i]; //ich sehe kein malloc/new } position+=bytes; return ok; } return out_of_range; } return stream_not_open; }
sehe ich das richtig, dass du alles im speicher haeltst? was ist, wenn die datei n paar 100 MB gross ist?
result Virtualfile::open(char* Name){ //const vergessen //wobei ich sowieso lieber den ctor nehmen wuerde //man oeffnet naemlich keine datei mehr als 1 mal if(datapointer==NULL){ ifstream Data(Name); if(Data.is_open()){ Data.seekg(0,ios::end); size=Data.tellg(); Data.seekg(0,ios::beg); datapointer=malloc(size); if(datapointer!=NULL){ readpointer=(char*)(datapointer); position=0; name=Name; char Buffer; for(unsigned int i=0;i<size;++i){ Data.read(&Buffer,sizeof(char)); //sehr lahm readpointer[i]=Buffer; } Data.close(); //unnoetig return ok; } size=0; Data.close(); //unnoetig return failed; } return wrong_arguments; } return stream_allready_open; }
und wieder keine exception...
-
ja ich halte alles im speicher, ja ich weis, dass es sehr viel werden kann, nein ich weis nicht, wie groß der heap ist,aber hab mal gelesen, dass alles was nicht stack ist für den heap reserviert ist.
das system soll für texturen modeldaten/animationsdaten usw sein,also alles was man mehrere male in kurzen abständen brauchen kann, und wo sich das ablegen im meory lohnt,ich plane ja auch schon ne 2. klasse die direkt aus der datei streamen kann(ich will die dateien aus großen archiven laden,deshalb sind die standard streamklassen nich so perfekt^^).
der ram is im gegensatz zur hd von der geschwindigkeit her einfach zu verlockend^^
so zu deinen kommentaren noch:
exceptions hab ich bisher noch nie benutzt, ist für mich also relatives neulandbeim rest kann ich dir soweit zustimmen, bis auf die sache mit malloc/new.. das problem ist, dass ich nicht überprüfen kann,ob schon speicher reserviert worden ist, und ich kann auch nicht sicher gehen, dass der speicher der von der read funktion reserviert wird auch wieder freigegeben wird.Die daten die rausgegeben werden können ja auch programmtechnisch ne längere lebensdauer als die klasse haben.
desweiteren wirds in den meisten fällen nicht nötig sein,speicher extra zu reservieren..(datei.read(Header,sizeof(header)//hier ist speicher reservieren unnötig, er existiert ja schon^^).und zu der sache mit ctor..ka was das ist, hab auf die shcnelle weder was in der bcb hilfe noch in meinem nachschlagewerk gefunden^^
//sehr lahm
so besser?
Data.read(readpointer,size);
-
ctor = Konstruktor und wenn du den nicht kennst, solltest du C++ mal richtig lernen.
Im Übrigen ist dies das Standard C++ Forum, weswegen man dir kaum etwas außerstandardmäßiges für so ein Problem empfehlen wird, die BCB Doku ist daher nicht einzusehen.
-
was ein konstruktor ist weis ich,ich kenn nur nicht die fachbegriffe.
und mein konstruktor macht das ja auch, aber ich hab ja in der Klasse noch die möglichkeit gelassen,die zieldatei zu ändern,also dass man zb im konstruktor eine virtuelle datei öffnet, danach mit ihr arbeitet, sie am ende wieder schließt, und dann wieder eine neue öffnet.
-
Konstruktor ist der Fachbegriff (und der einzige), ctor ist eine Abkürzung ;)...
Ansonsten machen die filestreams das doch auch, dass man neu öffnen kann, bei Bedarf, oder was meinst du jetzt, Shade?
-
so, es funktioniert jetzt, es lag an der zeile:if(position+range<size){ hätte <= sein müssen^^
hab auch grad mal den geschwindigkeits unterschied zwischen normalem read und meinem read getestet...beide sind 10millionen mal durchgelaufen..
als zieldatei musste eine 33kb gro0e textdatei herhalten
standard stream 2223
mein stream 140(!)
noch deutlicher wirds beim seek,da hab ich zuerst an der beg.pos dann end.pos dann cur.pos gemessen
standard stream:8652|27250|11570
mein stream:161|141|140diese werte überaschten mich jetzt doch ziemlich,deshalb hab ich nochmal alles nachgeprüft,ob ich nich irgendwo messfehler drin hatte, aber seht selbst:
vfile::Virtualfile file; file.open("b.txt"); int k=GetTickCount(); for(int i=0;i<10000000;++i){ file.seek(0,vfile::end_pos); } cout<<GetTickCount()-k<<endl; file.close(); ifstream datei("b.txt"); int l=GetTickCount(); for(int i=0;i<10000000;++i){ datei.seekg(0,ios::end); } cout<<GetTickCount()-l;
also ich denke, der ärger hat sich gelohnt,oder was meint ihr?
-
@Mis2Com:
jo, std::fstream hat auch ne open methode und close. Aber die streams sind ja auch mies designt. Der Designer davon (hab leider den namen vergessen) gibt es ja auch zu und hat gemeint, dass er einiges anders machen wuerde, wenn er sie neu designen koennte.@otze:
natuerlich ist es schneller alles zuerst in den speicher zu laden.
die streams sind ja auch nicht fuer das schnelle auslesen aus einer datei gemacht - sie puffern ja wie wildbtw: was misst du denn da? nur das seek alleine? und das ganze auslesen dass du im open machst, ignorieren wir schoen... nicht sehr representativ...
und bitte: verwende exception und den ctor und dtor statt open und close. wenn du nicht weisst warum, google mal nach RAII
nix fuer ungut, aber deine klasse ist nicht so toll.
zB bei einem 100MB file stehst du an.ausserdem allokiert deine read methode keinen speicher - somit ist dein urspruenglicher code (mit dem ach so mysterioesen fehler) fehlerhaft.
-
shade? ich glaub wir reden aneinander vorbei
die read methode darf garkeinen speicher allokieren, das würde zu gigantischen speicherleaks führen.
wenn ne datei geöffnet wird, wird entweder sofort oder mittels open ein stream auf die zieldatei geöffnet, sie wird vermessen, dann mit dem wert der speicher reserviert, und die datei reingeschrieben.
wenn die klasse den scope verlässt wird der platz wieder freigegeben.
die read methode soll dann nur angeforderte mengen speicher in einen anderen speicherbereich transferieren.
read darf nicht new/malloc benutzen,was man auch an folgendem code sehen kann:header Header; datei.open("file.txt"); datei.read((*void)(&Header),sizeof(header));//hier ein new und wir haben ein schönes speicherleck,der cast muss da sein, //da ich keine templates benutzen kann,und deshalb eine version für void zeiger machen musste^^ //anderes Beispiel char data[256]; datei.read(data,256);//speicherleck bei new char* subdata=new char[256]; datei.read(subdata,256);//keiner erklärung mehr von nöten
zum thema open und ausmessen...seek wird andauernd durchgeführt read auch,open dagegen fast garnicht, also wieso testen? ist uninteressant,was nu länger braucht.
Und 100mb Files sind ne schöne sache, die werden nur partweise ausgelesen,oder direkt mittels stream,daran hab ich schon gedacht.
andererseits haben zb modeldaten die angewohnheit, dass man da wild rumseeken muss,und da hat so ein memorystream einen echten heimvorteil
-
result Virtualfile::read(char* &buffer,unsigned int bytes){
if(datapointer!=NULL){
if(position+bytes<size){
for(unsigned int i=0;i<bytes;++i){
buffer*=readpointer[position+i]; // KUCKUCK
}
position+=bytes;
return ok;
}
return out_of_range;
}
return stream_not_open;*Ob ich C++ kann oder nicht, ist mir jetzt egal, Fakt ist, dass du in der Zeile [i]KUCKUCK* diesen Buffer, den man übergibt, beschreibst und dafür dass du ihn beschreibst, muss Speicher vorhanden sein, den du nicht allokiert hast.
Und es handelt sich auch nicht um irgendeinen Stream, auf den du schreibst, du schreibst in den Buffer und der ist nicht definiert, da du bisher einfach einen Zeiger angelegt hast, der irgendwo hin zeigt.Jedenfalls sehe ich das so:
void irgendwas(char*& bla) { for(int n = 0; n < 100; ++n) bla[i] = 'a'; // irgendwas } char* a; irgendwas(a);
Somit schreibst du irgendwo in den Speicher, ob es da hingehört oder nicht.
Das Ergebnis sollte undefiniert sein, oder nicht?
In diesem Fall MUSS Speicher allokiert werden und das ist nicht im Gegenteil ein Speicherleck, es sei denn, du vergisst delete natürlich.Nagut, offensichtlich bin ich blind, man kläre mich auf...
-
wenn ich ausserhalb der funktion speicherplatz für ein objekt reserviere, und innerhalb der funktion dann mit einer referenz auf dieses objekt(bzw dem zeiger auf den speicherplatz den das objekt reserviert hat)arbeite,dann brauch ich nicht nochmal speicherplatz reservieren, denn er ist ja schon reserviert.
und nun stellen wir uns mal vor, ich reserviere ausserhalb der funktion speicher, übergebe den zeiger auf diesen speicher, und versuche dann mittels new nochmal speicher für diesen pointer zu reservieren.
ich kann nur vermuten was passieren kann:
1. undefiniertes verhalten
2. der pointer zeigt auf den gleichen bereich
3. der pointer wird einem neuen bereich zugeordnet, dabei entsteht ein speicherleck, da der vorher reservierte speicher nichmehr deleted wird.
//edit nach selbstversuch: 3 trifft zues besteht natürlich wie man in meinem ersten veralteten beispiel sehen kann die gefahr, illegal speicher zu belegen,aber solange mir niemand sagen kann,wie man testen kann, ob speicher reserviert wurde, bleibt das so.
-
Dein read-Methode stellt in keinem Fall Speicher für buffer bereit, wenn doch, so zeige mir die Zeile.
-
hallo? liest du überhaupt was ich schreibe? ich will garkeinen speicher zur verfügung stellen.
ich will als funktionsparameter einen zeiger auf einen speicherbereich,den der programmierer in irgendeiner weise schon freigegeben hat.
seis new, oder einfache reservierung des speichers auf dem stack, das is mir egal.
es ist also die schuld des benutzers der read funktion, wenn er undefiniertes verhalten erhält,das hab ich aber auch schon irgendwo geschrieben bzw eingeräumt, da ich ja am amfang denselben fehler gemacht hab(auch wenn der eigentliche fehler woanders lag).
-
Selber hallo.
Du schreibst in deiner Funktion in buffer rein und zwar recht viel.
Und dieser Speicher ist NIRGENDWO allokiert, in deinem Beispiel nicht außerhalb und innerhalb der read-Funktion auch nicht, es ist mir völlig egal, was du willst, du kannst unallokierten Speicher nicht einfach vollschreiben.
Wenn du innerhalb der read-Funktion keinen Speicher bereitstellst, so musst du dies außerhalb tun, aber das tust du nicht, folglich schreibst du in nicht-allokierten Speicher.Seufz, was ist daran so schwer zu verstehen?
-
ok nochmal ganz ganz langsam extra für dich-.-
//dies ist jetzt ein erklärendes beispiel char bla[254] //es werden 254 bytes auf dem stack reserviert,sagen wir von der //datenposition 16 aus,der reserviertespeicher geht also von 16-259 cout<<bla//hier wird die datenposition also 16 ausgegeben //so irgendwo später im code nachdem eine datei geöffnet wurde data.read(bla,254); //hier wird der zeiger auf die position 16 und die info über die anzahl der zu //kopierenden daten(zufälligerweise die größe des vorher reservierten speichers)übergeben //innerhalb der funktion result Virtualfile::read(char* &buffer,unsigned int bytes){ //durch die übergabe des zeigers auf den speicherbereich 16 zeigt buffer nun auch auf 16(siehe funktionen und parameter) buffer[1]//da der buffer den wert 16 hat zeigt buffer[1] 1 bit weiter->17->innerhalb des reservierten bereichs also ok buffer=readpointer[position+i]//zulässig solange es im reservierten bereich bleibt //das selbe gilt für readpointer->malloc //usw usf
.