[HELP] Files kopieren :: Zugriffsverletzung
-
Hi,
ich habe ein Prog, das macht Backup von Dateien, die bestimmte Extensions haben.
Das läuft wunderbar bei sogut wie jedem.
Allerdings hat ca jeder 500ste ein "Zugriffsverletzung un Modul ...".
Das muss beim Kopieren der Dateien auftreten. Ich habe schon versucht die Dateien per WinAPI-Funktionen zu kopieren und auch per High-Level mit FILE-Pointer.
Bei den "Problemfällen" klappt aber all das nicht.Einer von denen hat mal sein OS neu aufgespielt und danach hat es funktioniert.
Auch die Windows-Versaonen kann man nicht festmachen. Mal XP mal W2k mal ...Hat jemand ne Idee, wie ich noch kopieren könnte?
Oder ist es möglich, dass ne andere BCB-Version (ich benutze BCB5) das so kompiliert, dass es auf den "ProblemPCs" läuft?
Ich bin ziemlich ratlos.
Danke im Voraus!MfGr,
Mid
-
Poste doch mal den Quellcode, womit du die Datei öffnest und speicherst. Eine Zugriffsverletzung kann normalerweise nichts mit anderen Dateien zu tun haben.
-
Also wie gesagt, habe ich mehrere Varianten probiert. 2x WinAPI und einmal HighLevel. Also schiebt micht nicht wieder ins WinAPI, wenn ich das hier losgeschickt habe.
Variante 1:
// Funktion fCopy() int fCopy(AnsiString *orgName, AnsiString *bakName, int runs) { FILE *fp1, *fp2; unsigned int c; char *fin, *fout; for (int i=0; i<runs; i++) { // Dateien öffnen fp1 = fopen( (*(orgName + i)).c_str(), "rb"); fp2 = fopen( (*(bakName + i)).c_str(), "wb"); // Dateiinhalte kopieren while ( ( c = getc(fp1) ) != EOF ) putc( c, fp2 ); // Dateien schließen fclose(fp1); fclose(fp2); } return 0; }
Variante 2:
int fCopy ( AnsiString *orgName, AnsiString *bakName, int runs ) { // Datei orgName nach bakName kopieren // runs = Anzahl der gefundenen *.part.met for (int i=0; i<runs; i++) { // falls CopyFile () fehlschlägt, Wert ungleich 0 zurückliefern // an aufrufende Funktion if ( CopyFile ( (*(orgName + i)).c_str(), (*(bakName + i)).c_str(), false ) == 0 ) return 1; } return 0; }
Variante 3:
int fCopy ( AnsiString *orgName, AnsiString *bakName, int runs ) { HANDLE hSrc, hDest; char pBuffer[1024]; DWORD dwRead, dwWritten; // Datei orgName nach bakName kopieren // runs = Anzahl der gefundenen *.part.met for (int i=0; i<runs; i++) { // Quelldatei öffnen - Handle ermitteln hSrc = CreateFile ( (*(orgName + i)).c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ); // falls ungültiges Handle, dann Abbruch und entspr. Return-Wert if ( hSrc == INVALID_HANDLE_VALUE ) { Application->MessageBox( MSG_FAILED_A, BOXTITLE_ERROR, MB_OK ); return 1; } // Zieldatei öffnen - Handle ermitteln hDest = CreateFile ( (*(bakName + i)).c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); // falls ungültiges Handle, dann Abbruch und entspr. Return-Wert if ( hDest == INVALID_HANDLE_VALUE ) { Application->MessageBox( MSG_FAILED_A, BOXTITLE_ERROR, MB_OK ); return 1; } // Kopiervorgang do { ReadFile(hSrc, pBuffer, sizeof(pBuffer), &dwRead, NULL); if (dwRead != 0) WriteFile(hDest, pBuffer, dwRead, &dwWritten, NULL); } while (dwRead != 0); // Handles schließen CloseHandle(hSrc); CloseHandle(hDest); return 0; } }
Ich habe mir diese Funktionen jeweils so geschrieben, dass ich neben den Arrays, die die Filenamen enthalten auch gleichtzietig ne Zahl übergebe, die sagt, wieviele Dateinamen übergeben wurden, ergo wieviele Kopiervorgänge notwendig sind. Und die werden dann auch gleich durchgeführt.
greetz,
mid
-
ok, jetzt bitte noch die exakte Fehlermeldung und die ungefähre Position wo dieser Fehler auftritt.
-
zugriffsverletzung
> bei adresse 00481298 in modul "pmbackup v1.1e.exeEs ist irgendwo in der fCopy Funktion. Ich kann das leider nicht genauer lokalisieren, da ich diese Fehlermeldung selbst noch nie erhalten habe. Ich hbas nur von 3-4 Usern per Mail erhalten. Sorry. Ich weiß ja selbst nicht mehr, woran das noch liegen kann.
-
hm,
mir sind bei den Windowsversionen über Version 98 deraretige Probleme auch schon aufgefallen. Dateien lassen sich nihct schreiben, obwohl Schreibrechte auf dem Laufwerk existieren.
Am besten ist, wenn man I/O- Funktionen benutzt die Betriebssystem spezifisch angeboten werden. Ich würde hier also mit API arbeiten. Variante 3 scheint mir also am besten geeignet. Allerdings solltest du CopyFile benutzen.
Ansonsten überprüfe du im Zielverzeichnis schreibrechte hast.
Siehe FILE_ATTRIBUTE_READONLY
und _WIN32_FIND_DATA oder ähnliches...ich kann mir aber nihct vorstellen, das bei dieser Geschichte eine Zugriffsverletztung bei herausspringen soll. WriteFile wird da false zurückliefern ( warum fragst du das eigentlich nicht ab, um dich zu vergewissern, dass der Vorgang erfolgreich war) aber keine Zugriffsverletztung rausschmeissen. Die Zugriffsverletztung kommt woanders her..
-
Hi Andreas,
ich danke Dir,
ich werd mir das nochmal alles genauer anschauen müssen und vielleicht noch ein paar Daten mehr sammeln, von den Leuten, bei denen es nicht geht.Thanks anyway!
mid
-
Ich schiebe diese mal nach API. Vieleicht haben die dort noch Lösungsansätzte.
-
In allen 3 Versionen hast du sowas:
(*(orgName + i)).c_str()
Daran liegt es ganz bestimmt. Du übergibst also 2 dynamisch angelegte AnsiString-Arrays mit der Länge runs. Hmm, versuch mal lieber sowas wie
orgname[i].c_str()
Sieht mir sicherer aus.
-
(*(orgName + i)).c_str(),
ohje, hab ich glatt übersehen...
-
Aber eigentlich müsste es ja das gleiche sein. Nur wer weiß, wie Borland genau die Klasse AnsiString implementiert hat. Ich weiß nur, dass die Klasse basierend auf Assembler-Code geschrieben wurde. Naja, ich habe jedenfalls kein gutes Gefühl, wenn ich diese Zeigeroperation da sehe.
-
Hi Leute,
Ich änder das mal ab.
Das seltsame ist halt nur, dass es bei 99,5 Prozent der Fälle klappt.
Mal schauen was wird.Danke!
-
Huups, da habe ich eine Idee. Wie wäre es, mit TStringList zu arbeiten:
// Funktion fCopy() bool fCopy(TStringList* orgNames, TStringList* bakNames) { if(!orgNames || !bakNames) return false; if(orgNames->Count != bakNames->Count) return false; FILE *fp1, *fp2; unsigned int c; for (int i=0; i<orgNames->Count; i++) { // Dateien öffnen fp1 = fopen(orgNames->Strings[i].c_str(), "rb"); fp2 = fopen(bakNames->Strings[i].c_str(), "wb"); // Dateiinhalte kopieren while ( ( c = getc(fp1) ) != EOF ) putc( c, fp2 ); // Dateien schließen fclose(fp1); fclose(fp2); } return true; }
Das ist das Sicherste!
[ Dieser Beitrag wurde am 10.03.2003 um 00:18 Uhr von WebFritzi editiert. ]
-
Danke für den Klasse Tip Fritzi, ich werde das mal einbauen und an so nen Problemfall schicken.
Aber mal noch was anderes zu dieser "Zeigeroperation" *smile*
files = ( AnsiString * ) calloc ( anzMets, MAX_PARTMET_FILENAME_LENGTH );
files = ( AnsiString * ) calloc ( anzMets, MAX_PARTMET_FILENAME_LENGTH );Meine MAX_PART... hab ich mit 15 definiert.
Nehmen wir an, ich finde 500 Files mit meinem FindFirst/-Next.
Die 500 steht dann in anzMets.
Das ergibt doch bei meinen Mathe-Kentnissen 7500. Wenn ich nun bei den überwachten Ausdrücken *(files + 6000) angebe, dann sollte doch da NULL oder ein Filename auftauchen. Ab *(files + 4500) etwa steht nicht mehr NULL da, wenn noch nix reingeschrieben ist, sondern ????. Ist das so ein Anzeichen, was Du meintest in Bezug auf Ansistring und meine Zeigerspielchen ?Falls ja, dann sollte ich mich wohl davon distanzieren, sowas zu tun.
greetz,
mid
-
Original erstellt von Midnighter:
Ist das so ein Anzeichen, was Du meintest in Bezug auf Ansistring und meine Zeigerspielchen ?Nö. Das ist ganz normal. Du allokierst ja Seicher, und da kann alles drin stehen. Aber mir wird jetzt einiges klar. Du benutzt für jeden AnsiString pauschal 15 Bytes. Bei den Problemfällen wird es wohl so sein, dass es genug Files gibt, deren Pfade lang genug sind, so dass der AnsiString mehr als 15 Bytes umfasst. Wir arbeiten nicht umsonst mit dem C**++**Builder. Deshalb benutzen wir new. Wenn du also schreiben würdest
AnsiString* files; files = new AnsiString[anzMets];
würde alles gutgehen. Ich plädiere trotzdem für den Einsatz von TStringList, denn genau für sowas ist diese Klasse da.
-
Original erstellt von WebFritzi:
Ich plädiere trotzdem für den Einsatz von TStringList, denn genau für sowas ist diese Klasse da.Jepp, das habe ich auch soeben so ähnlich, wie Du gepostet hast implementiert. Hab nur zum Kopieren weiterhin WinAPI-Funktionen verwendet.
Hab mir damit ne Zählvariable gespart und ne Menge verschenkten Speicher, weil ich wegen dem ganzen Kram schon mit dem Gedanken gespielt habe, einige Array statisch zu machen.
Thx, dass Du mich an dem wirklich super Einfall hast teilhaben lassen!
N8,
mid