Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

1

19.09.2012, 20:23

Absturz bei return

Hallo.
Ich arbeite gerade an einem "Packer", der mir Daten packt und entpackt. Beim Entpacken gibt es Probleme. Ich benutze folgenden Code um eine Datei aus dem Gepackten zu schreiben:

C-/C++-Quelltext

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
27
28
29
30
31
32
33
34
35
36
int readtofile( const char *filename, const char *archivename )
    {
        FILE *writefile;
        UINT32 len, i;
        char buf[1024];
        for( i  =  0; i < anz; i++ )
        {
            if( !strcmp( dic[i].name, archivename ) )
                break;
        }
        if( i >=  anz )
            return 1;

        fseek( dat, dic[i].off, SEEK_SET );
        len  =  dic[i].len;
        //*******************************
        std::string s;
        fread(&s, sizeof(std::string), 1, dat);
        char* fn = const_cast<char*>(s.c_str());

        //*******************************
        fopen_s( &writefile, fn, "wb" );
        if( writefile  ==  NULL )
            return 2;

        while( len > 1024 )
        {
            fread( buf, 1, 1024, dat );
            fwrite( buf, 1, 1024, writefile );
            len -=  1024;
        }
        fread( buf, 1, len, dat );
        fwrite( buf, 1, len, writefile );
        fclose( writefile );
        return 0;
    }

Der Debugger zeigt nirgendwo einen Nullpointer bei den Dateien. Kann man also ausschließen. Die Zugriffsverletzung entsteht erst bei return 0;
DebugLibary: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Ich weiß nicht mehr weiter, was da falsch ist. Die Datei ist dann vollständig geschrieben. Nur der Absturz nervt ein wenig...
Der Code nach der Funktion, ist der Ausstieg aus der Nachrichtenfunktion von Windows.
Danke für jede Hilfe.

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

2

19.09.2012, 22:00

Kann es sein, dass der Rücksprung aus der Funktion irgendwelche Destruktoren aufruft, die die Zugriffsverletzung verursachen?

P.S. Das sieht sehr sehr böse aus:
std::string s;
fread(&s, sizeof(std::string), 1, dat);

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

3

19.09.2012, 22:46

Laut Debugger nein. Ich werde morgen mal mehr Code zeigen. Darf ich fragen, was an dem fread so schlimm ist?

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

4

19.09.2012, 22:54

Die 2 Zeilen düften für den Fehler verantwortlich sein.

fread speichert die gelesenen Zeichen an der im ersten Parameter angegebenen Adresse ab. std::string ist jedoch ein komplexes Objekt, das selbst u.a. einen Zeiger auf char besitzt (also auf den eigentlichen String). Du manipulierst den Speicher des Objekts - nicht den Zeiger auf char.

Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
struct foo
{
    char *string;
};

foo f;
fread(&f, sizeof(foo), 1, dat);


Wird das String-Objekt in deinem Code bei return zerstört, enthält es demnach nur noch ungültige Daten und Zeiger.

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

5

20.09.2012, 21:09

Alles klar dann mache ich das doch mit char*.
Schreiben:

C-/C++-Quelltext

1
2
char* fnn = filename + iLastBackSlash + 1;
fwrite(&fnn, 1, strlen(fnn) + 1, dat);

Jetzt gibt es nur ein Problem. Ich kenne die Länge des zu lesendem nicht... Wie kann ich das jetzt wieder in ein char Pointer/Array einsetzen?

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

20.09.2012, 21:25

Du musst da wohl erst die Länge des Strings schreiben oder aber mit 0 terminieren und jedes Byte einzeln lesen, bis die 0 gefunden ist. Beide Varianten sind üblich.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

7

20.09.2012, 21:28

Warum verwendest du nicht einfach std::fstream (in Verbindung mit std::stringstream falls notwendig):
http://stackoverflow.com/questions/13235…o-istringstream
Mit diesen veralteten C-Funktionen machst du dir das Leben unnötig schwer und das zuungunsten der Typsicherheit, wie du bemerkt hast.

Was bezweckst du mit char* fnn = filename + iLastBackSlash + 1;? Dir ist schon klar, dass du für deine Zeiger Speicher reservieren musst (dies kannst du auch dynamisch je nach Dateigröße tun)?!

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

8

20.09.2012, 21:55

@BlueCobold: Werde mich dran veruschen.

Zitat von »BurningWave«

Dir ist schon klar, dass du für deine Zeiger Speicher reservieren musst (dies kannst du auch dynamisch je nach Dateigröße tun)?!
Autsch... Das habe ich wohl verpennt....

Mein bisheriger Code, der auch die Länge dazu schreibt.
Schreiben:

C-/C++-Quelltext

1
2
3
4
5
6
char* fnn = new char[4096];
fnn = filename + iLastBackSlash + 1;

unsigned int i = strlen(fnn);
fwrite(&i, sizeof(unsigned int), 1, dat);
fwrite(&fnn, 1, strlen(fnn) + 1, dat);


Lesen:

C-/C++-Quelltext

1
2
3
4
unsigned int si;
fread(&si, sizeof(unsigned int), 1, dat);
char* fn = new char[si + 1];
fread(fn, si, 1, dat);

Das Lesen schlägt fehl. Ich bekomme immer nur drei Zeichen, die in "fn" stehen.
Auch mit fread(fn, 1, si, dat); geht es nicht.

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

9

20.09.2012, 22:09

fnn = filename + iLastBackSlash + 1;
Das funktioniert nicht. Du arbeitest hier mit Zeigern. Hier wird zur Adresse von filename iLastBackSlash und 1 addiert, jedoch keineswegs der String kopiert. Du müsstest strcpy() verwenden. Tu dir den Gefallen und verwende sofort std::string.

Genauso ist fread(&si, sizeof(unsigned int), 1, dat); Quatsch oder möchtest du 4 Bytes lesen und sie in einem Integer speichern?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

20.09.2012, 22:23

Genauso ist fread(&si, sizeof(unsigned int), 1, dat); Quatsch oder möchtest du 4 Bytes lesen und sie in einem Integer speichern?

Öh, nee, die Zeile is schon ok. 4 Byte sind ein Integer, jap.

ifstream und ofstream, sowie std::string sollten aber trotzdem dringend verwendet werden und kein alter und unsicherer C-File-Mist.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige