Access Violation Fehler, Invalid Pointer operation [gelöst]
-
Hallo,
Zu den Fehlern
1. das delete für datei und Dateiname_neu muß so aussehendelete[] datei;etc.
2. Du machst ein delete von datei in der Schleife, d.h. du machst das 3-mal ohne vorher neuen Speicher anzufordern1. Bemerkung:
Warum verwendest du überhaupt char-Felder. Dein ganzer Code läßt sich problemlos ausschließlich mit AnsiString (oder std::string) realisieren. Dann hast du auch keine Probleme mit dem Speicher mehr.
2. Bemerkung
Warum verwendest du fopen und Konsorten. In C++ verwendet man für sowas eher Streams.Ciao
-
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 HauptfunktionLeider 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_verzeichnisseansehe, 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 freigebenwieder 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 machenAnsiString 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 machenAnsiString 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]
.
.
OliHallo 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 + NameEs 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
