[c++] Object uit een binary file lezen gaat mis bij string

Pagina: 1
Acties:

  • Hmail
  • Registratie: April 2003
  • Laatst online: 08-04 13:17

Hmail

Doet ook maar wat.

Topicstarter
Ik ben bezig met het schrijven van een tooltje die onder andere leest en schrijft van een bestand. Het compileren gaat prima, dus de code zou moeten werken. Toch krijg ik een error zodra het programma afgelopen is. Het gaat om deze error:
*** glibc detected *** double free or corruption (fasttop): 0x0804b020 ***
^^ Dit is dus @ Linux. Ook onder Windows werkt het niet, daar krijg ik een veel grotere error waar ik net zo veel wijs uit kan worden:
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!

Program: ...
File: dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)
---------------------------
Afbreken Opnieuw Negeren
---------------------------
Ik ben er achter gekomen dat de fout zou moeten zitten in het feit dat ik een string wil lezen uit een binair bestand. Ik kan dit misschien het beste duidelijk maken met een beetje code :)
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// De class...
class Tekst
{
    private:
        int ID;
        string text;
    // Public gedeelte met constructor en lidfuncties
}
// De functie waar het om gaat:
void readfile(string naam_in)
{
    ifstream bestand2(naam_in.c_str(), ios::binary);
    Tekst LeesBestand;
    if(bestand2.read(reinterpret_cast<char*>(&LeesBestand), sizeof(Tekst)))
    { 
    bestand2.close();
    // Het lezen gaat goed!
    LeesBestand.Display();
    }
    else
    {
    // code als het fout gaat
    }
}

Vrij eenvoudig dus. Display is een lidfunctie die gewoon de waardes van een object op het scherm zet.

Zodra ik van text een int maak gaat het prima, dus de fout zit hem in het feit dat ik een string gebruik. Van de uitleg van Google en GoT search begrijp ik niet zo heel veel. Moet ik me echt gaan verdiepen in object serialization, wat dat ook wezen mag, of is het probleem makkelijker op te lossen?

Voor de geinteresseerden heb ik m'n code ook even geupload, misschien dat mijn code niet volledig genoeg is, dus hierbij: http://geensite.nl/zooi2/simout.cpp

[ Voor 5% gewijzigd door Hmail op 21-02-2006 21:31 ]

It might sound as if I have no clue what I'm doing, but I actually have a vague idea.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Nee hoor, ook met een int gebeurd er niet wat jij denkt. Je krijgt misschien geen fout omdat er weinig fout kan gaan aan een int, maar werken doet het zeker niet.

Je kan objecten simpelweg gewoon niet zo wegschrijven. Structs wel, maar die mogen dan geen pointers bevatten of referenties naar classes zoals string.

We adore chaos because we like to restore order - M.C. Escher


  • Hmail
  • Registratie: April 2003
  • Laatst online: 08-04 13:17

Hmail

Doet ook maar wat.

Topicstarter
Volgens het boek wat ik heb, "Aan de slag met C++", is dat juist niet zo. Toevallig kwam ik net een forum tegen waar iemand een stukje netjes heeft overgetikt uit het boek, dit topic, en dan de 2e reply. Die code laat toch zien dat het wel kan, of begrijp ik je verkeerd?

[ Voor 13% gewijzigd door Hmail op 21-02-2006 21:43 ]

It might sound as if I have no clue what I'm doing, but I actually have a vague idea.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Nee, ook dat werkt niet volgens de posts in die thread. Die 2e post is van dezelfde gozer als de eerste post en de oplossing in die thread gebruikt geen class.

We adore chaos because we like to restore order - M.C. Escher


  • Hmail
  • Registratie: April 2003
  • Laatst online: 08-04 13:17

Hmail

Doet ook maar wat.

Topicstarter
Klopt, ik bedoelde eigenlijk ook alleen de code uit de 2e post. Voor de duidelijkheid zal ik het even copy/pasten en wat beter toelichten:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class Punt {
private:
int x, y;
public:
Punt(int x= 0, int y = 0)
:x (x), y(y) {
}
};

int main()
{
string filename = "bestand5.dat";
Punt A, B( 2, 3), C(17,21);
ofstream bestand(filename.c_str(), ios:: binary);

bestand.write(reinterpret_cast<char*> (&A), sizeof(Punt));
bestand.write(reinterpret_cast<char*> (&B), sizeof(Punt));
bestand.write(reinterpret_cast<char*> (&C), sizeof(Punt));

cout << "Binair bestand" << filename << "is geschreven.";
}

Bovenstaande code is dus rechtstreeks afkomstig uit hetzelfde boek als dat ik gebruik. Aan de hand van die code heb ik mijn applicatie gemaakt. Het probleem van E-programmeur is een heel ander probleem, dus ook de oplossing heeft niks met mijn probleem te maken :P
Aan de hand van die code heb ik grotendeels mijn programma gebruikt. Zoals je ziet gebruik ik ongeveer dezelfde methode als het boek, alleen heb ik hier en daar een aanpassing, en gebruik ik wat andere classes.
Ik ben er vanuit gegaan dat de code uit m'n boek klopt en goed is, dus niet met fouten die je niet ziet. Als dat niet het geval is kan ik het net zo goed uit het raam gooien :P

It might sound as if I have no clue what I'm doing, but I actually have a vague idea.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Tja, ik ben geen C++ veteraan, dus ik kan het mis hebben. Zelfs als het bovenstaande voorbeeld goed is in C++ gaat het niet goed bij pointers. Netzoals het niet zou werken bij een struct overigens. Wat er hier gebeurd is namelijk dat de botte layout van de class in het geheugen wordt opgeslagen in het bestand. Pointers die je zo ook opslaat wijzen naar onzin als je ze weer terug zou lezen.

We adore chaos because we like to restore order - M.C. Escher


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:30

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als dat boek niet uitlegt dat dit werkt omdat een int een primitive is die je net als alle andere primitives gewoon binair kunt lezen en schrijven dan kun je het idd beter uit het raam gooien. Er zijn 2 problemen: pointers/references en typen met een constructor/destructor. Pointers naar disk schrijven heeft natuurlijk geen nut, je hebt er niets aan dat in een bestand staat op welk geheugenadres de data te vinden is, aangezien dat geheugen weg is zodra het proces afgesloten wordt.

Voor objecten met een gedefinieerde constructor is het meer de semantische correctheid die in het geding is. Elk object heeft een bepaalde lifetime, die start met de constructor en eindigt met de destructor. Voordat de constructor en nadat de destructor gelopen hebben is het geen object meer maar gewoon wat ongeïnitialiseerd geheugen. En die objecten zijn buiten de methode-aanroepen door gewoon in een goed-gedefinieerde staat. Als jij een object aanmaakt en zijn data vervolgens compleet overschrijft met wat binaire data uit een file is die staat niet meer gedefinieerd. Voor hetzelfde geldt heeft het object zichzelf bij het aanmaken ergens geregistreerd, en worden er elders dus bepaalde aannames over dat object gemaakt. Je kunt dan z'n data niet zomaar overschrijven. Wat je dan moet doen is gewoon functies maken die het object kunnen serialiseren, oftewel lezen en schrijven van/naar een binaire representatie.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Hmail
  • Registratie: April 2003
  • Laatst online: 08-04 13:17

Hmail

Doet ook maar wat.

Topicstarter
.oisyn en LordLarry, ongelofelijk bedankt voor jullie uitleg _o_ Ik heb dan nog geen werkende app, maar ik weet tenminste waardoor die fout komt :)
Als ik jullie uitleg goed begrijp ben ik gewoon een pointer, dus een verwijzing naar een geheugenadres aan het schrijven naar m'n harde schijf. Als ik het lezen en schrijven in losse applicaties, dus als de destructor is aangeroepen is, ga doen, dan word er dus bij het lezen een verwijzing gelezen naar crap. Een andere applicatie heeft dat adres waarschijnlijk dan allang gebruikt, dus dat werkt voor geen meter.
Doordat ik beiden in 1 applicatie gebruikte was er nog geen destructor aangeroepen, dus werkte het wel, maar kreeg ik de mysterieuze foutmelding :)

Ik ga me verdiepen in object serialisatie, mijn dank is groot!

offtopic:
En dat boek hou ik toch nog even, ondanks het feit dat de auteur een belangrijk stukje vergeet is dat toch het boek waaruit ik C++ heb geleerd :+

It might sound as if I have no clue what I'm doing, but I actually have a vague idea.


Verwijderd

C++ Faq Lite geeft een redelijk duidelijke uitleg over serialization.
Pagina: 1