ein absolut "kranker" fehler



  • ok, mal was zu lachen 😉

    int main(int argc, char* argv[])
    {
        int blub;//ganz doll wundern^^
        int i;
        vfile::Virtualfile file;
        file.open("3DSINFO.TXT");//datei in speicher einlesen
        char* data;
        file.read(data,file.get_size());//inhalt des speichers in variable
        for(unsigned int i=0;i<file.get_size();++i){
            cout<<data[i];//ausgabe der datei,bei long double in der blub variable gibts access violation in module bla^^
        }
        file.close();
        cin>>i;
        return 0;
    }
    

    die variable blub hats richtig drauf, auch wenn ich sie nirgendwo in meinem ganzen qc rest verwende 😉
    der qc ist ein test meiner virtuellen speicherklasse, es wird automatisch speicher auf dem heap reserviert,dann die datei reingeschrieben,und später mit read wieder ausgelesen.
    nun zu der variable blub:
    solange an der stelle irgendeine variable ist,funktioniert alles tadellos,die datei wird also ausgegeben.
    ohne die variable..nunja zeichensalat.
    dabei macht es aber auch keinen unterschied, welche variable da oben steht, ich kann den typ(mit ausnahme von long double, dann gibts ne acces violation^^) und/oder den namen ändern, aber entfernen darf ich die variable nicht, ist an der stelle ne leerzeile, oder wenn ich die zeile komplett lösche, gibts..ja genau zeichensalat^^

    hab mir den zeichensalat mal angeschaut,zwischendurch kommen da zeichenfolgen wie diese:pure virtual function called/___CPPdebugHook/basic string und sogar:
    Borland C++ - Copyright 2002 Borland Corporation

    und ich dachte schon der erste april wäre vorbei 😃
    und nein, das ist KEINE verarsche^^



  • mal ehrlich:
    wo reservierst du speicher, bzw. wo gibst du ihn wieder frei?



  • ich reserviere mit malloc, und die klasse kümmert sich selber um die freigabe des speichers mithilfe des destruktors

    Virtualfile::~Virtualfile(){
        free(datapointer);
    }
    

    //edit achja ich kann die erste variable löschen, wenn ich dafür die variable i auf double/long double setze,dann bleibt er aber auch mitten im text stehen,wenn ich aber dann hinter bzw vor i eine char variable setze, rattert er einmal bis weit ausserhalb des endes durch^^
    aber das geht nur bei double, wenn ich ne char variable vor/nach long double i setze, gibts ne access violation...ich fühl mich so langsam verarscht^^



  • hier mal ein paar algemeine tipps:

    c++ programmierer lassen destruktoren arbeiten, also file.close() explizit zu schreiben ist unnötiger quellcode balast
    c++ programmierer lassen konstruktoren arbeiten,

    vfile::Virtualfile file;
        file.open("3DSINFO.TXT");//datei in speicher einlesen
    

    besser weil es standard ctor aufruf spart und weiter optimierungen spart:

    vfile::Virtualfile file("3DSINFO.TXT");//datei in speicher einlesen
    

    nur wenn es sehr umständlich ist auf eine methode open zu verzeichten, erst dann darfs du sie implementieren

    char* data;
        file.read(data,file.get_size());//inhalt des speichers in variable
    

    kriegt read eine referenz auf den pointer?

    und sonst ist das wirklich häslich, wenn der speicher in read allociert wird und in main deallociert
    -schon in diesen kleinen programm hast du ein speicherleck (wenn file.close() nicht den speicher freigibt 🙄 )



  • 1.der destruktor deallociert auch
    2. close ist dafür da, damit ich einmal den speicher wieder freigeben kann, um ne neue datei einzulesen, die klasse kann nämlich nur eine datei gleichzeitig verarbeiten.
    3. close ist dazu da, um etwas besser mit dem speicher haushalten zu können-was ich nur 1x brauch, ist so ganz schnell wieder aus dem speicher raus.
    4. konstruktor gibts auch mit direkt laden
    5. ja read bekommt referenz auf den pointer
    6. wenn du willst kann ich den kompletten code posten-.-
    7. die klasse ist weitestgehend an fstream orientiert(nur nicht ganz so komplex)



  • 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 neuland 😃

    beim 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|140

    diese 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 wild 😉

    btw: 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...


Anmelden zum Antworten