Access Violation Fehler, Invalid Pointer operation [gelöst]



  • Habe jetzt die deletes und die Stellen, an denen sie ausgeführt werden geändert.

    Code:

    //Hauptfunktion
    int main(int argc, char* argv[])
    {
    	// Variablendeklaration
    	FILE *f;                                                            // FILE structure wird angelegt
        char* datei = new char[64];                                         // Zeiger auf Datei
        AnsiString verzeichnis1="\\bla1";  // Verzeichnis 1
        AnsiString verzeichnis2="\\bla2";      // Verzeichnis 2
        AnsiString verzeichnis3="\\bla3";                  // Verzeichnis 3
        AnsiString verzeichnis;                                             // aktuell gewähltes Verzeichnis
        int i_verzeichnisse=0;                                              // Zähler für die Verzeichnisse (3 Stück)
    
        for (i_verzeichnisse=0; i_verzeichnisse<=2; i_verzeichnisse++)  // Für alle drei Verzeichnisse
        {
            // Je nach Stand des Verzeichniszählers das entsprechende Verzeichnis auswählen
            if (i_verzeichnisse==0)         // Verzeichnis 1
            {
                verzeichnis=verzeichnis1;
            }
            else if (i_verzeichnisse==1)    // Verzeichnis 2
            {
                verzeichnis=verzeichnis2;
            }
            else if (i_verzeichnisse==2)    // Verzeichnis 3
            {
                verzeichnis=verzeichnis3;
            }
    
            // Verzeichnis anpassen + Variablendeklaration
            sprintf(datei, "%s%s", verzeichnis, "\\DATEI.txt");         // Dateinamen + Pfad ins Feld schreiben
            AnsiString Dateiname = datei;                               // Dateiname + Pfad als AnsiString, für umbenennen und dateidatum auslesen
        	char zeile[1000];                                           // Array in dem die Zeile gespeichert wird
    
            // +++ Datei öffnen +++
            if ((f = fopen(datei, "r"))==NULL)  // Wenn DATEI NICHT VORHANDEN
            {
                // Fehler
                cout << "Fehler: Datei nicht gefunden!\n";
            }
            else    // Wenn DATEI VORHANDEN
            {
    
                // +++ Dateidatum auslesen +++
                char datei_aenderungsdatum[10];                                 // Speicherplatz für das ermittelte Dateiänderungsdatum
                char datei_aenderungsdatum_sqlformat[10];                       // Speicherplatz für das ermittelte Dateiänderungsdatum
                Dateidatum_auslesen_anpassen(Dateiname, datei_aenderungsdatum, datei_aenderungsdatum_sqlformat); // Funktion zum Auslesen und anpassen des Dateiänderungsdatums
    
                // Datei umbenennen
                if (i_verzeichnisse!=2) // Wenn Datei geprueft und verschoben wurde
                {
                    // Variablendeklaration
                    char* Dateiname_neu = new char[64];
                    sprintf(Dateiname_neu, "%s%s %s.%s", verzeichnis, "\\DATEI", datei_aenderungsdatum_sqlformat, "txt");
                    AnsiString Dateiname_neuStr = Dateiname_neu;
    
                    if (RenameFile(Dateiname,Dateiname_neuStr))
                    {
                        cout << " Datei wurde umbenannt in " << Dateiname_neu << "!\n\n";
                    }
                    else
                    {
                        textcolor(LIGHTRED); //Farbe
                        cprintf("%s", " Fehler: Datei konnte nicht umbenannt werden!");
                    }
                    delete[] Dateiname_neu;   // Speicher freigeben
                }
                else if (i_verzeichnisse==2) // Wenn Datei nicht geprueft wurde (umbenennen + verschieben!)
                {
                    char* Dateiname_neu = new char[64];
                    sprintf(Dateiname_neu, "%s%s %s.%s", verzeichnis, "\\nicht_geprueft\\DATEI", datei_aenderungsdatum_sqlformat, "txt");
                    AnsiString Dateiname_neuStr = Dateiname_neu;
    
                    if (RenameFile(Dateiname,Dateiname_neuStr))
                    {
                        cout << " Datei wurde umbenannt und verschoben nach " << Dateiname_neu << "!\n\n";
                    }
                    else
                    {
                        textcolor(LIGHTRED); //Farbe
                        cprintf("%s", " Fehler: Datei konnte nicht umbenannt werden!\n");
                    }
                    delete[] Dateiname_neu;   // Speicher freigeben
                } // end else
    
            fclose(f);  // Datei schließen
            }   // end else
        delete[] datei;   // Speicher freigeben        
        }   // end for
    
        getch();
        return 0;
    }	//Ende der Hauptfunktion
    

    Leider funktioniert es immer noch nicht. Fehler:
    Project raised exception class EAccessViolation with message 'Access violation at address 011941E4. Write of address 38685C5C'. Process stpped. Use Step or Run to continue. [OK] [Help]

    Der Zeiger zeigt jetzt auf die Zeile:
    char* Dateiname_neu = new char[64];

    Wenn ich mir den Wert von

    i_verzeichnisse
    

    ansehe, beträgt dieser 1, also tritt der Fehler erst beim zweiten Durchlauf der Schleife

    if (i_verzeichnisse!=2) // Wenn Datei geprueft und verschoben wurde
                {
                    // Variablendeklaration
                    char* Dateiname_neu = new char[64];
    

    auf. Könnte es eventuell sein, dass der selbe Speicher zweimal reserviert wird, oder sowas in der Art? Obwohl es je eigentlich mit

    delete[] Dateiname_neu;   // Speicher freigeben
    

    wieder gelöscht werden sollte, oder?

    Zu den Bemerkungen:
    AnsiString benutze ich nicht, da es sich auf der Konsole nicht ausgeben lässt. Zumindest nicht mit cout <<...
    Und std::string klappt mit den Funktionen nicht.
    Müsste ich bei der Verwendung von Strings nicht auch die Funktionen wie z.B. sprintf() verändern?

    Kann mir vielleicht jemand ein Beispiel geben, wie ich es besser als mit char arrays machen kann?

    Fopen müsste doch eigentlich trotzdem funktionieren, auch wenn es vielleicht nicht so chic ist, oder?

    Danke für die Hilfe, MFG
    dope_dope



  • Zuerst zu deinen Kommentaren zu meinen Bemerkungen
    1.
    für cout mit AnsiString
    dann mußt du das ein wenig anders machen

    AnsiString test("test");
    cout << test.c_str();
    

    siehe auch FAQ bzw. die Hilfe zu den Memberfunktionen von AnsiString.
    Bei std::string ist das ähnlich. Auch die besitzen überladene Operatoren für + und += sowie die Funktion c_str().

    2. sprintf gibt es auch bei Ansistring (als Memberfunktion). Du kannst es aber auch einfach mit + bzw. += machen.
    Bsp.

    // deine Version
    sprintf(datei, "%s%s", verzeichnis, "\\DATEI.txt");
    
    // wenn datei AnsiString ist
    datei = verzeichnis;
    datei += "\\Datei.txt";
    

    Zum Fehler
    Könnte am delete[] von datei liegen. Verschiebe das mal eine Klammer nach unten. Du machst das delete ja in der for-Schleife (ohne neues new).



  • Braunstein schrieb:

    Zuerst zu deinen Kommentaren zu meinen Bemerkungen
    1.
    für cout mit AnsiString
    dann mußt du das ein wenig anders machen

    AnsiString test("test");
    cout << test.c_str();
    

    siehe auch FAQ bzw. die Hilfe zu den Memberfunktionen von AnsiString.
    Bei std::string ist das ähnlich. Auch die besitzen überladene Operatoren für + und += sowie die Funktion c_str().

    Man kann auch direkt AnsiString verwenden, wenn man das aus der BCB-Hilfe beachtet :

    Wenn Sie #include <iostream> oder #define VCL_IOSTREAM angeben, bevor Sie die include-Anweisung für die Datei dstring.h (die normalerweise indirekt durch die Datei vcl.h einbezogen wird) festlegen, können Sie die Streaming-Operatoren (<< und >>) mit AnsiStrings als Argument verwenden:

    ostream& operator << (ostream& os, const AnsiString& arg);
      istream& operator >> (istream& is, AnsiString& arg);
    

    bis bald
    akari



  • [cpp]// Variablendeklaration
    char****** Dateiname_neu = new char[64];[/cpp]

    Der Rückgabetyp des Ausdrucks

    new char[64];
    

    ist nämlich ein Pointer auf ein Feld von char.

    Vielleicht liegt's daran.

    Oli

    [Edit]
    P.S. Leider habe ich Unrecht. Der Rückgabetyp ist ein char*. 🙄
    [/Edit]



  • Hallo Oli,

    Lies dir bitte deinen eigenen Post nochmal durch. Deine Aussage ist falsch.



  • der oli schrieb:

    [cpp]// Variablendeklaration
    char****** Dateiname_neu = new char[64];[/cpp]
    .
    .
    Oli

    Hallo Oli, hier nicht, Das hier ist kein Zeiger auf Zeiger!!!



  • Das sagte ich bereits (zumindest so ähnlich 😉 ).



  • bin dabei, mich selbst aufzuklären.

    oli



  • hab jetzt folgendes verändert:

    Alt:

    char* datei = new char[64];               
       sprintf(datei, "%s%s", verzeichnis, "\\Datei.txt");
    

    Neu:

    AnsiString datei;
       datei = verzeichnis;
       datei += "\\Datei.txt";
    

    Problem:

    if ((f = fopen(datei, "r"))==NULL)
    

    fopen braucht anscheinend nen char-array.

    Wie würdet ihr das machen??? Das char-array lassen und wieder Angst vor Speicherfehlern 😞 oder kann man das wieder umwandeln und was war das mit diesen Streams? Leider is die Suchfunktion ja im Moment eher unbrauchbar..



  • Hallo,

    1. siehe FAQ
    2. Was für Probleme hast du mit den Streams?



  • Das FAQ-Beispiel hat geholfen, allerdings hab ich seitdem die Speicherfehler weg sind das Problem, dass das Umbenennen der Datei nicht mehr funktioniert. Habt ihr dazu eine Idee???



  • Was genau funktioniert denn nicht.
    Da wir deinen neuen Code nicht kennen und meine Kristallkugel auch in der Reperatur ist, weiß ich erstmal nicht weiter. 😉



  • Hab den Code weiter oben schonmal gepostet... aber hier nochmal einen Ausschnitt:

    Die Datei ist auf jeden Fall vorhanden, das wid mit:

    if ((f = fopen(datei, "r"))==NULL)  // Wenn DATEI NICHT VORHANDEN
            {
                // Fehler
                cout << "Fehler: In Verzeichnis " << i_verzeichnisse+1 << " wurde die gesuchte Datei nicht gefunden!\n\n";
            }
            else    // Wenn DATEI VORHANDEN
            {
    // Code...
    

    geprüft.

    Umbenannt wird hier (Forsetzung von else):

    if (RenameFile(DateiPfad_Name,Dateiname_neuStr))
                    {
                        cout << " Datei wurde umbenannt und verschoben nach " << Dateiname_neuStr.c_str() << "!\n\n";
                    }
                    else
                    {
                        textcolor(LIGHTRED); //Farbe
                        cprintf("%s%d%s", "Fehler: Datei in Verzeichnis ", i_verzeichnisse+1, " konnte nicht umbenannt werden!\n");
                    }
    

    Variablen:

    AnsiString DateiPfad_Name;  // Alter Dateipfad + Name
                    AnsiString Dateiname_neuStr; // Neuer Dateipfad + Name
    

    Es wird auch keine Fehlermeldung vom Compiler ausgegeben, das Programm läuft und zeigt dann den else-case (Konnte nicht umbenannt werden) an. Aber warum???



  • Schau doch mal nach ob eine Datei mit dem neuen Namen bereits existiert. Vielleicht ist deine Datei aber auch noch offen.
    Desweiteren schau mal in die Hilfe zu FileExists.



  • Hey, das ist die Lösung, wie soll er sie auch umbenennen, wenn sie noch offen ist... 💡

    Big fat thx 😉


Anmelden zum Antworten