AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) C++ "Invalid Argument" bei read und write
Thema durchsuchen
Ansicht
Themen-Optionen

"Invalid Argument" bei read und write

Ein Thema von PAX · begonnen am 12. Nov 2006 · letzter Beitrag vom 21. Nov 2006
Antwort Antwort
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#1

"Invalid Argument" bei read und write

  Alt 12. Nov 2006, 18:22
Nabend!

Nachfolgender Codeausschnitt soll eine Liste von Dateien zusammenfügen. Es wird dabei die erste Datei genommen und der Inhalt der restlichen Dateien Schritt für Schritt so schnell wie möglich angehängt.
Bei kleinen Dateien funktioniert das auch, aber bei mehreren zig MB Größe scheint ein Fehler aufzutreten, sowohl beim Einlesen, als auch beim Schreiben. Wenn ich immer nur 1 Byte gleichzeitig verarbeite, dann funktionierts fehlerfrei (ist aber zu langsam). Deshalb hab ich schon vermutet, dass es daran liegt, dass ich für den Zeiger "buffer" enorm viel Platz reservieren lasse - aber wenn das so in diesem Ausmaß nicht möglich ist, müsste mir das dann nicht der Compiler vorher sagen oder zumindest während der Programmausführung eine AV auftreten? Jedenfalls wird die Fehlervariable beim Öffnen der Datei und dem Setzen des Dateizeigers auf "Fehler 0" (kein Fehler) gesetzt, nur beim Lesen und Schreiben nachher sitzt sie auf "ungültiges Argument".
Also manchmal regt mich C++ auf! Sowas hatte ich bei Delphi bisher noch nie erlebt ! Hat jemand von euch eine Ahnung, worin das Problem liegt? Laut der Hilfe kann read oder write maximal UINT_MAX-1 Bytes lesen/schreiben.

Beste Grüße

Delphi-Quellcode:

  int quelldatei, zieldatei;
  unsigned long long groesse, geschrieben = 0;
  char *buffer = new char[UINT_MAX];

  zieldatei = open(Form1->Pfade->Strings[0].c_str(), O_WRONLY | O_BINARY, S_IREAD|S_IWRITE);
  lseek(zieldatei, 0, SEEK_END);
  for(unsigned long long i=1; i<Form1->Pfade->Count; i++) {
        quelldatei = open(Form1->Pfade->Strings[i].c_str(), O_RDWR | O_BINARY);
        groesse = lseek(quelldatei, 0, SEEK_END);
        lseek(quelldatei, 0, SEEK_SET);

        if(groesse > UINT_MAX-1) { //dieser Teil wird nicht ausgeführt
                geschrieben = groesse;

                while(geschrieben > UINT_MAX-1) {
                        read(quelldatei, buffer, UINT_MAX-1);
                        write(zieldatei, buffer, UINT_MAX-1);
                        geschrieben -= UINT_MAX-1;
                }


                read(quelldatei, buffer, geschrieben);
                write(zieldatei, buffer, geschrieben);
        } else { //dieser Teil wird ausgeführt und die Fehlermeldungen werden ausgegeben
                read(quelldatei, buffer, groesse); Application->MessageBoxA(_sys_errlist[errno],"Quelldatei lesen");
                write(zieldatei, buffer, groesse); Application->MessageBoxA(_sys_errlist[errno],"Zieldatei schreiben");
        }


        close(quelldatei);
  }
  close(zieldatei);
  delete buffer;
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#2

Re: "Invalid Argument" bei read und write

  Alt 12. Nov 2006, 19:03
Hi,
nur so ein Tipp (bin mir nicht sicher ob hier der Fehler liegt), versuch mal statt dem buffer die Adresse des ersten Elements zu übergeben, also:

Code:
read(quelldatei, &buffer[0], groesse); Application->MessageBoxA(_sys_errlist[errno],"Quelldatei lesen");
write(zieldatei, &buffer[0], groesse); Application->MessageBoxA(_sys_errlist[errno],"Zieldatei schreiben");
Ich weiß nicht wie C++ Arrays aufgebaut sind, aber da sie von den normalen C-Arrays abweichen sollte hier buffer und &buffer[0] wieder etwas anderes sein, dann kann es schonmal krachen.

Wie gesagt, nur eine Vermutung,
Gruß Der Unwissende
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#3

Re: "Invalid Argument" bei read und write

  Alt 12. Nov 2006, 19:44
Hallo Andreas,

kennt dein C++-Compiler keinen stream i/o? Wenn nicht, dann halte ich 4GB für einen verdammt großen Puffer - 64KB wären wohl eher angebracht. Auch würde ich prüfen ob mindestens 2 Pfade vorhanden sind, bevor ich die Arbeit aufnehme. Die Laufvariable i scheint mir auch hoffnungslos überdimensioniert zu sein. Warum öffnest du die Quelldateien für Lesen und Schreiben? Musst du die Größe der Quelldatei durch lseek() bestimmen? Das geht bestimmt auch direkt (fsize?) über die Metadaten im Verzeichniseintrag. Die Verarbeitungsschleife scheint mir unbrauchbar zu sein. Ein brauchbares Muster stelle ich mir etwa so vor:

Code:
// ...
        rest = groesse;
        while (rest > 0) { 
               gelesen = read(quelldatei, buffer, BUF_SIZE);
               geschrieben = write(zieldatei, buffer, gelesen);
               rest -= geschrieben;
        }

// ...
Hierbei unterstelle ich, dass die Schreib- und Leseaufrufe die tatsächlich verarbeiteten Mengen zurückgeben.

Freundliche Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#4

Re: "Invalid Argument" bei read und write

  Alt 15. Nov 2006, 18:07
ok, ich danke euch zunächst erstmal.
vorweg: ich hatte in diesen tagen nicht die zeit gefunden, mich wieder mit diesem problem zu befassen, aber ich habe ein frage an dich, marabu: warum ausgerechnet 64KB als puffergröße?
gut, 4gb is sehr viel, da habe ich garnicht dran gedacht, geschweige denn, es mal vorsichtshalber ausgerechnet. ähm, wird jedem prozess nicht maximal 4gb zugesprochen? dann hätte doch eine fehlermeldung kommen müssen, oder nicht? weil auf diese pufferreservierung von 4gb würde doch dann noch ein bisschen vom programm an sich heraufkommen?

ja, stimmt, die laufvariable braucht nicht so groß sein, weil sie ja immer mit der anzahl der einträge in der listbox verglichen wird, welche als rückgabewert von typ integer ist. ich würde gerne so viele listboxeinträge wie möglich aufnehmen können, was bei integer nicht in dem ausmaß wie bei unsigned long long möglich ist - frage: was passiert, wenn die maximale anzahl an einträgen überschritten wird? ... ok, hab gerade mal nachgeschaut, das wären ungefähr 2 milliarden einträge, dürfte also erstmal reichen !

ich weiß garnicht mehr, warum ich die dateigröße über fseek ermittle, es gab jedenfalls irgendein problem bei fsize, kann jetzt aber nicht sagen, was das noch war - ich glaube, fsize lieferte manchmal inkorrekte rückgabewerte... vielleicht auch in verbindung damit, wenn währenddessen die datei von nem anderen programm geöffnet war (fileseek kann zwar in diesem fall auch nicht gesetzt werden, liefert jedoch -1 zurück, wodurch ich diesen fehlerfall überhaupt erkennen kann).
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#5

Re: "Invalid Argument" bei read und write

  Alt 15. Nov 2006, 19:28
Hi,

die 64KB kommen aus dem Bauch. Den worst case hast du ja schon mit deinem single byte i/o erlebt. Beim file i/o überlagern sich ja mehrere Puffer auf verschiedenen Ebenen. Die performance deines Programms steigt mit wachsender Puffergröße an, fällt allerdings irgendwann auch wieder ab, wenn der Puffer zu groß gewählt wird. Mit einem kleinen Testprogramm (100 Zeilen schätze ich) könntest du den optimalen Durchsatz ausloten.

Gute Nacht
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#6

Re: "Invalid Argument" bei read und write

  Alt 16. Nov 2006, 13:08
Zitat von marabu:
Mit einem kleinen Testprogramm (100 Zeilen schätze ich) könntest du den optimalen Durchsatz ausloten.
könnte dies aber auch von der verwendeten maschine, auf dem das programm läuft, stark abhängen?
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#7

Re: "Invalid Argument" bei read und write

  Alt 16. Nov 2006, 13:18
Ja sicher doch. Die einzelnen Pufferbereiche sind ja unterschiedlich groß. Die Festplatte selbst hat einen Track Buffer und einen Cache, der von Modell zu Modell variieren kann. Das Dateisystem hat einen Cache, der von der Größe des Hauptspeichers und dem momentanen Verhandlungsstand der Betriebssystem-Komponenten abhängt, ...

Warum hängst du die Dateien nicht einfach per shell command hintereinander?

Code:
 copy /b quelle-*.dat ziel.dat
Freundliche Grüße
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#8

Re: "Invalid Argument" bei read und write

  Alt 17. Nov 2006, 14:34
Zitat von marabu:
Warum hängst du die Dateien nicht einfach per shell command hintereinander?
Code:
 copy /b quelle-*.dat ziel.dat
weil das betreffende programm die dateien auch spalten kann. da würde ich ein schlechtes gewissen haben, wenn es dann nicht auch noch den service bietet, sie wieder zu verschmelzen.

das programm copy arbeitet doch bestimmt auch so, gell? wie viele bytes verarbeitet es selber denn gleichzeitig? ich möchte nachher nicht langsamer sein, als copy.

beste grüße
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.152 Beiträge
 
Delphi 12 Athens
 
#9

Re: "Invalid Argument" bei read und write

  Alt 17. Nov 2006, 15:20
Zur Puffergröße:

ich hab beim meinem Rechner und mit verschiedenen Laufwerken (Puffern) die grenze bei 2*515 KB gelegt.

Ab 2*1 MB (paralell auf einer Platte gelesen) fiehl die Datenrate wieder ab.


eine 2-Potenz als Größe ist eigentlich am Besten.

Ansonsten macht sich wohl das 4- bis 8-fache der "größtens" Blocks recht angenehm.

Von den leicht ermittelbaren Größen lassen sich wohl der Windowsseitenspeicher (aktuell 64 KB je Block) und dann noch die Clustergröße der Festplatte ermitteln.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#10

Re: "Invalid Argument" bei read und write

  Alt 21. Nov 2006, 13:06
Zitat von himitsu:
Zur Puffergröße:

ich hab beim meinem Rechner und mit verschiedenen Laufwerken (Puffern) die grenze bei 2*515 KB gelegt.

Ab 2*1 MB (paralell auf einer Platte gelesen) fiehl die Datenrate wieder ab.


eine 2-Potenz als Größe ist eigentlich am Besten.

Ansonsten macht sich wohl das 4- bis 8-fache der "größtens" Blocks recht angenehm.
was ist in diesem fall mit block gemeint?

Zitat von himitsu:
Von den leicht ermittelbaren Größen lassen sich wohl der Windowsseitenspeicher (aktuell 64 KB je Block) und dann noch die Clustergröße der Festplatte ermitteln.
also ab 2MB sinkt die geschwindigkeit wieder. das wäre dann als 2er-potenz:

Delphi-Quellcode:
oben := 2048*1024 Byte = 2097152 Byte

ld oben = potenz

ln oben / ln 2 = ld oben = 21


2^21 Bytes = oben
ich müsste also am besten weniger als 2^21 Bytes verarbeiten? hängt diese schranke allerdings von den besagten größen (clustergröße, windowsseitenspeicher) ab? wie bekomme ich diese werte und in welchem zusammenhang stehen sie formeltechnisch?

beste grüße
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:30 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz