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

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

1

18.04.2006, 19:51

Win32API Datei-Funktionen-Problem

Hallo!

Wie mir nix da empfohlen hat, versuche ich jetzt meinen Code auf die File-Functions der WinAPI umzuschreiben... Nur funktionierts irgendwie nicht, und ich weiß einfach nicht wieso! Ich bekomm ein gültiges Handle, und auch GetLastError gibt mir 0 zurück, aber dann, sobald ich was schreiben will, gibt er mir eine Access violation --> unbehandelte Ausnahme.... Hier der Code:

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
template <typename T>
ogResult ogUtilsWriteStructToFile(wchar_t* sFileName, T* Structur)
{
    //Paramenter

    if(!sFileName) OG_ERROR_NULL_POINTER(L"sFileName", OG_ERROR);
    if(!Structur) OG_ERROR_NULL_POINTER(L"Struktur", OG_ERROR);

    //Datei öffnen

    HANDLE hFile = ::CreateFileW(sFileName,             //Datei

                                 GENERIC_WRITE,         //Rechte

                                 0,                     //Shared-Rechte

                                 NULL,                  //Sicherheitsattribute

                                 OPEN_ALWAYS,           //Verhalten bei speziellen Situationen

                                 FILE_ATTRIBUTE_NORMAL, //Attribute

                                 NULL);
    DWORD dwError = ::GetLastError();    // == 0

    if(hFile == INVALID_HANDLE_VALUE)
    {
        return OG_ERROR;  //Hier kommt er NIE her!

    }

    //Daten in die Datei schreiben

    ::WriteFile(hFile, Structur, sizeof(T), NULL, NULL); //Und hier crasht das Programm!!


    //Hanlde schließen

    ::CloseHandle(hFile);

    return OG_OK;
}
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

Anonymous

unregistriert

2

18.04.2006, 20:02

Liegt daran, dass Deine Parameter sich gegenseitig blockieren.

C-/C++-Quelltext

1
    if ((file_handle = ::CreateFileW (file_.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)


Hab es nur schnell ausm Kopf gemacht.

Das Problem ist, Du benutzt "OPEN_ALWAYS", dazu steht in der Doku:

Zitat

Opens a file, always.
If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.

Anonymous

unregistriert

3

18.04.2006, 20:27

Ach quatsch, was erzähl ich denn da? Totaler unsinn. (Na ja, fast)

Problem ist Deine WriteFile-Funktion, nämlich die letzten beiden Parameter.
Zum vorletzten Parameter steht folgendes in der MSDN:

Zitat

[out] Pointer to the variable that receives the number of bytes written. WriteFile sets this value to zero before doing any work or error checking.
If lpOverlapped is NULL, lpNumberOfBytesWritten cannot be NULL. If lpOverlapped is not NULL, lpNumberOfBytesWritten can be NULL. If this is an overlapped write operation, you can get the number of bytes written by calling GetOverlappedResult. If hFile is associated with an I/O completion port, you can get the number of bytes written by calling GetQueuedCompletionStatus.

If I/O completion ports are used and you are using a callback routine to free the memory allocated to the OVERLAPPED structure pointed to by the lpOverlapped parameter, specify NULL as the value of this parameter to avoid a memory corruption problem during the deallocation. This memory corruption problem will cause an invalid number of bytes to be returned in this parameter.


Nun, da Du den letzten Parameter nicht gefüllt hast, knallt es. (Ist klar! Keine Sicherheitsabfrage und Windows weiß nicht wie weit es gehen darf.)

Hab mal ein kleines Beispiel geschrieben, wie man es anständig macht um Text in eine Datei reinzustopfen.

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
#include <windows.h>

void foobar (wchar_t* value)
{
        // Dateiname

    wchar_t*            file                = "test.txt";

        // Daten für das Dateihandling

    void*               file_handle         = NULL; // Handle auf die Datei

    unsigned long       file_writtenbytes   = 0;    // Hilfsvariable für die geschriebenen Bytes


        // Datei erstellen/öffnen

    if ((file_handle = ::CreateFileW (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
        EXCEPTION (L"Die Datei '%s' konnte nicht erstellt werden!", file);

        // Text schreiben (und direkt anhand der anzahl geschriebener Bytes prüfen ob es Fehler gab!!!!)

    if (!::WriteFile (file_handle, value, static_cast<unsigned long>(::wcslen(value) << 1), &file_writtenbytes, NULL) || file_writtenbytes != static_cast<unsigned long>(::wcslen(value) << 1))
    {
        ::CloseHandle (file_handle);
        EXCEPTION (L"Schreiboperation in Datei '%s' ist nicht korrekt verlaufen!", file);
    }
    
        // Wehe es vergisst einer das schließen der Datei! Das kann böse knallen!

    ::CloseHandle (file_handle);
}

int main (void)
{
    foobar (L"dies ist ein Testtext!");

    return 0;
}

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

4

18.04.2006, 20:53

Danke... Das mit dem 1. NULL hab ich wohl überlesen :( sry
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

Anonymous

unregistriert

5

18.04.2006, 20:56

Black-Panther
Macht nix, aber vergiss NIEMALS das überprüfen der wirklich geschriebenen/gelesenen Bytes! Teste es so wie ich das gemacht habe.

Es kann nämlich gelegentlich kleinere Sachen bei Prozessen und Rechteverwaltung eine Blockade geben (z. B. 2 Tasks versuchen gleichzeitig auf die Datei zuzugreifen, z. B. das eine Sucht nach Updates das andere wird gelesen).

Vorallem beim schreiben ist dies unbedingt notwendig, denn sonst bekommste irgendwann fehlerhafte Dateien und weißt nix davon! Beim lesen sollte man es auch teste, damit man der Graka keine "kaputten" Daten gibt für ne Textur und so.

Diese Sicherrungen sind z. B. nicht mit in den Standard integriert der STL ;)

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

6

18.04.2006, 21:16

Jo, werd ich machen, danke....

Jetzt ist aber auch schon das nächste Problem aufgetaucht, und zwar, wird jetzt die Datei erfolgreich geöffnet und beschrieben, aber wenn ich das Programm das nächste mal starte, und die Datei, welche vorher angelegt habe, auslesen will, bekomm ich eine ERROR_SHARING_VIOLATION... Aber sharing tritt ja nur auf, wenn bereits ein Prozess diese Datei verwendet! oder?! Selbige wird aber NUR von einem Prozess ERSTELLT UND GELESEN! Beides sind abgeschlossene Situationen, bei beiden, wird das handle wieder geschlossen, und trotzdem kommt so ein Fehler...
Da muss ich wohl was falsch verstanden haben....:

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
template <typename T>
ogResult ogUtilsReadStructFromFile(wchar_t* sFileName, T* Structur)
{
    //Paramenter

    if(!sFileName) OG_ERROR_NULL_POINTER(L"sFileName", OG_ERROR);

    //Datei öffnen

    HANDLE hFile;
    if((hFile = ::CreateFileW(sFileName,                //Datei

                              GENERIC_READ,             //Rechte

                              0,                        //Shared-Rechte

                              NULL,                     //Sicherheitsattribute

                              OPEN_EXISTING,            //Verhalten bei speziellen Situationen

                              FILE_ATTRIBUTE_NORMAL,    //Attribute

                              NULL)) == INVALID_HANDLE_VALUE)
    {
        DWORD dwErr = ::GetLastError();
        OG_ERROR_FILE(sFileName, OG_ERROR);
    }

    //Daten in die Datei schreiben

    DWORD   dwBytesRead = 0;
    if((!::ReadFile(hFile, Structur, sizeof(T), &dwBytesRead, NULL)) || dwBytesRead < sizeof(T))
        OG_ERROR(L"Es trat ein Fehler beim Schreiben einer Datei auf!", OG_ERROR);

    //Hanlde schließen

    ::CloseHandle(hFile);
    
    return OG_OK;
}
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

Anonymous

unregistriert

7

18.04.2006, 21:22

Black-Panther
Verstehe ich das richtig? Du willst Schreiben in einem Prozess und Lesen im anderen gleichzeitig?

p.s.: Vergleiche auf != und nicht auf <, es können auch durch Pufferüberläufe mehr Daten geschrieben werden.

kurz: bissel genauer

Anonymous

unregistriert

8

18.04.2006, 21:43

Hab noch was gemacht: Funzt einwandfrei

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <windows.h> 

void foobar (wchar_t* value) 
{ 
        // Dateiname 

    wchar_t*            file                = L"test.txt"; 

        // Daten für das Dateihandling 

    void*               file_handle         = NULL; // Handle auf die Datei 

    unsigned long       file_writtenbytes   = 0;    // Hilfsvariable für die geschriebenen Bytes 


        // Datei erstellen/öffnen 

    if ((file_handle = ::CreateFileW (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
        EXCEPTION (L"Die Datei '%s' konnte nicht erstellt werden!", file); 

        // Text schreiben (und direkt anhand der anzahl geschriebener Bytes prüfen ob es Fehler gab!!!!) 

    if (!::WriteFile (file_handle, value, static_cast<unsigned long>(::wcslen(value) << 1), &file_writtenbytes, NULL) || file_writtenbytes != static_cast<unsigned long>(::wcslen(value) << 1)) 
    { 
        ::CloseHandle (file_handle); 
        EXCEPTION (L"Schreiboperation in Datei '%s' ist nicht korrekt verlaufen!", file); 
    } 
    
        // Wehe es vergisst einer das schließen der Datei! Das kann böse knallen! 

    ::CloseHandle (file_handle); 
} 

void foobar2 (wchar_t* value, unsigned long size) 
{ 
        // Dateiname 

    wchar_t*            file                = L"test.txt"; 

        // Daten für das Dateihandling 

    void*               file_handle         = NULL; // Handle auf die Datei 

    unsigned long       file_recievedbytes  = 0;    // Hilfsvariable für die gelesenen Bytes 


        // Datei öffnen 

    if ((file_handle = ::CreateFileW (file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
        EXCEPTION (L"Die Datei '%s' konnte nicht gefunden werden!", file); 

        // Text lesen und Sicherheitsprüfund durchführen!

    if (!::ReadFile (file_handle, value, size, &file_recievedbytes, NULL) || file_recievedbytes != size) 
    { 
        ::CloseHandle (file_handle); 
        EXCEPTION (L"Leseoperation in Datei '%s' ist nicht korrekt verlaufen!", file); 
    } 

        // Wehe es vergisst einer das schließen der Datei! Das kann böse knallen! 

    ::CloseHandle (file_handle); 
} 

int main (void) 
{ 
        // Text speichern

    wchar_t* text = L"dies ist ein Testtext!";
    foobar (text); 

        // text ist 22 zeichen lang (okay 23, nullterminierung zählt diesmal jedoch nicht)

    wchar_t buffer[22] = L"";

        // Text aus der Datei in Puffer reinschreiben. buffer ist 44 Byte groß, da 22*sizeof(wchar_t) = 44;

    foobar2 (buffer, 44);

        // Ausgeben

    std::wcout << buffer << std::endl;
    std::cin.get ();

    return 0; 
}

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

9

18.04.2006, 22:16

Also, nur zum Verständis... Es handelt sie hierbei um eine Datei, welche eine Struktur speichert, welche die Grafikkonfiguration beinhaltet (Auflösung, RefreshRate, Vollbildmodus j/n, usw).
Beim ersten Programm-Start (keine Datei vorhanden!) wird sie erstellt: FUNKTIONIERT!
Programm wird beendet!

Wird wieder gestartet, nun sollte die Datei eingelesen werden --> FEHLER! 32 --> ERROR_SHARING_VIOLATION!! Unverständlich, zumal dieser Funktionsaufruf mehr oder weniger einer der ersten überhaupt ist!
Danach kommt der Config-Dlg und dann sollte die Konfiguration wieder gespeichert werden --> FEHLER! Wieder schlägt das CreateFileW fehl... ka wieso

Anmerkung:
Hab jetzt beide Funktionen (fast) identisch mit deinen beiden.... und doch wills nicht... isch post hier mal den Code beider:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//Schreibt eine Struktur in eine Datei

template <typename T>
ogResult ogUtilsWriteStructToFile(wchar_t* sFileName, T* Structur)
{
    //Paramenter

    if(!sFileName) OG_ERROR_NULL_POINTER(L"sFileName", OG_ERROR);
    if(!Structur) OG_ERROR_NULL_POINTER(L"Struktur", OG_ERROR);

    //Datei öffnen

    HANDLE hFile;
    if((hFile = ::CreateFileW(sFileName,                //Datei

                              GENERIC_WRITE,            //Rechte

                              0,                        //Shared-Rechte

                              NULL,                     //Sicherheitsattribute

                              CREATE_ALWAYS,            //Verhalten bei speziellen Situationen

                              FILE_ATTRIBUTE_NORMAL,    //Attribute

                              NULL)) == INVALID_HANDLE_VALUE)
        OG_ERROR_FILE(sFileName, OG_ERROR);

    //Daten in die Datei schreiben

    DWORD   dwBytesWritten = 0;
    if((!::WriteFile(hFile, Structur, sizeof(T), &dwBytesWritten, NULL)) || dwBytesWritten != sizeof(T))
        OG_ERROR(L"Es trat ein Fehler beim Schreiben einer Datei auf!", OG_ERROR);

    //Hanlde schließen

    ::CloseHandle(hFile);

    return OG_OK;
}

//------------------------------------------------------------//


//Lest eine Struktur in eine Datei

template <typename T>
ogResult ogUtilsReadStructFromFile(wchar_t* sFileName, T* Structur)
{
    //Paramenter

    if(!sFileName) OG_ERROR_NULL_POINTER(L"sFileName", OG_ERROR);

    //Datei öffnen

    HANDLE hFile;
    if((hFile = ::CreateFileW(sFileName,                //Datei

                              GENERIC_READ,             //Rechte

                              0,                        //Shared-Rechte

                              NULL,                     //Sicherheitsattribute

                              OPEN_EXISTING,            //Verhalten bei speziellen Situationen

                              0,                        //Attribute

                              NULL)) == INVALID_HANDLE_VALUE)
    {
        DWORD dwErr = ::GetLastError();
        OG_ERROR_FILE(sFileName, OG_ERROR);
    }

    //Daten aus Datei lesen

    DWORD   dwBytesRead = 0;
    if((!::ReadFile(hFile, Structur, sizeof(T), &dwBytesRead, NULL)) || dwBytesRead != sizeof(T))
        OG_ERROR(L"Es trat ein Fehler beim Schreiben einer Datei auf!", OG_ERROR);

    //Hanlde schließen

    ::CloseHandle(hFile);
    
    return OG_OK;
}
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

Anonymous

unregistriert

10

18.04.2006, 22:26

Black-Panther
Ob das nun eine Struktur ist, ein Text, ein Array oder sonst was ist doch für das Schreiben absolut furz wie deckel. Byte bleibt Byte und ende.

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <windows.h> 

void foobar (void* value, unsigned long size) 
{ 
        // Dateiname 

    wchar_t*            file                = L"test.txt"; 

        // Daten für das Dateihandling 

    void*               file_handle         = NULL; // Handle auf die Datei 

    unsigned long       file_writtenbytes   = 0;    // Hilfsvariable für die geschriebenen Bytes 


        // Datei erstellen/öffnen 

    if ((file_handle = ::CreateFileW (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
        EXCEPTION (L"Die Datei '%s' konnte nicht erstellt werden!", file); 

        // Text schreiben (und direkt anhand der anzahl geschriebener Bytes prüfen ob es Fehler gab!!!!) 

    if (!::WriteFile (file_handle, value, size, &file_writtenbytes, NULL) || file_writtenbytes != size) 
    { 
        ::CloseHandle (file_handle); 
        EXCEPTION (L"Schreiboperation in Datei '%s' ist nicht korrekt verlaufen!", file); 
    } 
    
        // Wehe es vergisst einer das schließen der Datei! Das kann böse knallen! 

    ::CloseHandle (file_handle); 
} 

void foobar2 (void* value, unsigned long size) 
{ 
        // Dateiname 

    wchar_t*            file                = L"test.txt"; 

        // Daten für das Dateihandling 

    void*               file_handle         = NULL; // Handle auf die Datei 

    unsigned long       file_recievedbytes  = 0;    // Hilfsvariable für die gelesenen Bytes 


        // Datei öffnen 

    if ((file_handle = ::CreateFileW (file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
        EXCEPTION (L"Die Datei '%s' konnte nicht gefunden werden!", file); 

        // Text lesen und Sicherheitsprüfund durchführen!

    if (!::ReadFile (file_handle, value, size, &file_recievedbytes, NULL) || file_recievedbytes != size) 
    { 
        ::CloseHandle (file_handle); 
        EXCEPTION (L"Leseoperation in Datei '%s' ist nicht korrekt verlaufen!", file); 
    } 

        // Wehe es vergisst einer das schließen der Datei! Das kann böse knallen! 

    ::CloseHandle (file_handle); 
} 

struct my_struct
{
    unsigned long value_1;
    unsigned long value_2;
};

int main (void) 
{ 
        // Schreiben

    my_struct test = { 555, 666 };
    foobar (&test, sizeof(test));

        // Lesen

    my_struct test2;
    foobar2 (&test2, sizeof(test2));

        // Ausgeben

    std::cout << test2.value_1 << std::endl;
    std::cout << test2.value_2 << std::endl;

    std::cin.get ();

    return 0; 
}


Geht einwandfrei.

Frage: Was ist das für eine Struktur die Du abspeichern willst, habe da eine dunkle Vorahung.

Werbeanzeige