Mein C-Programm hat manchmal einen Speicherzugriffsfehler
-
Kann noch anhängen, daß für charweises Schreiben fputc() angebrachter wäre.
Noch'n Schwachpunkt:
Wo überwachst Du, daß Dir d1 und d2 nicht um die Ohren fliegen?
-
pointercrash() schrieb:
Kann noch anhängen, daß für charweises Schreiben fputc() angebrachter wäre.
char-weise mit putc dürfte ziemlich langsam sein.
Besser dürfte sein, mit malloc einen größeren Bereich zu reservieren, mit memset auf 0 zu setzen und den dann so oft schreiben bis die Datei überschrieben ist.
-
if(attribut.st_mode & S_IFREG) //Wenn Datei if(attribut.st_mode & S_IFDIR) //Verzeichnis
scheitern für den Fall, dass die Konstanten mehr als 1 Bit gesetzt haben.
Richtigerweise prüft man so:if( (attribut.st_mode & S_IFREG) == S_IFREG )
Auch schreibst du beim <zerstoeren> ans Ende der Datei, was wohl nicht beabsichtigt ist.
Warum kopierst du von d_name nochmal in einen eigenen Puffer, dass ist nur fehleranfällig, was du auch bewiesen hast.
-
DirkB schrieb:
pointercrash() schrieb:
Kann noch anhängen, daß für charweises Schreiben fputc() angebrachter wäre.
char-weise mit putc dürfte ziemlich langsam sein.
Unwahrscheinlich. putc ist ein Makro, das praktisch zu einer direkten Zuweisung in den Dateipuffer expandiert.
fputc ist dasselbe als Funktion, das könnte ein bisschen langsamer sein, aber immer noch nicht dramatisch.
-
Ich meinte den Vergleich von fputc zu fwrite bei vielen Daten. (Ich habe das f bei fputc vergessen)
-
Bashar schrieb:
DirkB schrieb:
pointercrash() schrieb:
Kann noch anhängen, daß für charweises Schreiben fputc() angebrachter wäre.
char-weise mit putc dürfte ziemlich langsam sein.
Unwahrscheinlich. putc ist ein Makro, das praktisch zu einer direkten Zuweisung in den Dateipuffer expandiert.
fputc ist dasselbe als Funktion, das könnte ein bisschen langsamer sein, aber immer noch nicht dramatisch.Naja, das ist schon langsamer, abhängig davon, wie groß die writebuffer sind und die Flushzykluszeit. Ich war ein wenig schreibfaul, eigentlich hätte ich noch mitliefern sollen, daß es ungünstig ist, mit "0" zu überlöschen. Das ist leichter rekonstruierbar, als wenn man mit rand() generierte Muster draufschüttet.
Ich glaub', beim US- Militär gilt eine Löschung nur, wenn ein paarmal (5?) mit zufälligen Mustern überschrieben wird.
-
fwrite schreibt doch in den gleichen Puffer, wieso sollte putc also langsamer sein? BTW geht es mir hier nicht um Haarspalterei, nur um die Aussage (f)putc sei "ziemlich langsam" mit der Andeutung, dass man das nicht verwenden sollte.
-
pointercrash() schrieb:
..., eigentlich hätte ich noch mitliefern sollen, daß es ungünstig ist, mit "0" zu überlöschen. Das ist leichter rekonstruierbar, als wenn man mit rand() generierte Muster draufschüttet.
Ich glaub', beim US- Militär gilt eine Löschung nur, wenn ein paarmal (5?) mit zufälligen Mustern überschrieben wird.Einmal überschreiben reicht : http://www.heise.de/newsticker/meldung/Sicheres-Loeschen-Einmal-ueberschreiben-genuegt-198816.html
-
Wutz schrieb:
if(attribut.st_mode & S_IFREG) //Wenn Datei if(attribut.st_mode & S_IFDIR) //Verzeichnis
scheitern für den Fall, dass die Konstanten mehr als 1 Bit gesetzt haben.
Richtigerweise prüft man so:if( (attribut.st_mode & S_IFREG) == S_IFREG )
Richtigerweise prüft man
if(S_ISREG(attribut.st_mode))
, wie man in POSIX nachlesen kann. POSIX lässt sich nicht darüber aus, ob es sich beim Dateityp-Teil von st_mode um eine Bitmaske handelt (obwohl sie üblicherweise so implementiert ist). Wird beispielsweise hochgezählt - S_IFREG = 1, S_IFLNK = 2, S_IFDIR = 3 - so wird dein Ansatz Verzeichnisse als reguläre Dateien erkennen. Nicht einmal
if((attribut.st_mode & S_IFMT) == S_IFREG)
ist in POSIX definiert, obwohl das der vor der Einführung der S_IS-Makros übliche Weg war, den Dateityp abzuprüfen und ich sehr erstaunt wäre, eine davon abweichende Implementation zu finden.
Es ist gut, sich um Korrektheit Gedanken zu machen, nur sollte man dann auch nachschlagen, was korrekt ist.
Was Performance angeht - ich hab das mal gebencht:
Mit fwrite:
real 0m0.294s user 0m0.020s sys 0m0.248s
Mit fputc:
real 0m1.259s user 0m1.016s sys 0m0.244s
Mit putc:
real 0m1.266s user 0m1.008s sys 0m0.256s
Code wie folgt:
#include <stdio.h> int main() { FILE *fd = fopen("test.txt", "w"); char block[1000] = { }; int i; for(i = 0; i < 100000; ++i) { fwrite(block, 1, 1000, fd); } /* for(i = 0; i < 100000000; ++i) { fputc(0, fd); // putc(0, fd); } */ return 0; }
System ist Linux 2.6.32 auf x86-64. Zu einem Teil hängt das mit Locking zusammen - benutze ich statt putc das (linux-spezifische) _IO_putc_unlocked-Makro, kommt Folgendes heraus:
real 0m0.633s user 0m0.392s sys 0m0.244s
Der Rest dürfte der Unterschied zwischen memcpy und einer Schleife mit Zuweisungen sein (nehme ich an).
-
Bashar schrieb:
fwrite schreibt doch in den gleichen Puffer, wieso sollte putc also langsamer sein? BTW geht es mir hier nicht um Haarspalterei, nur um die Aussage (f)putc sei "ziemlich langsam" mit der Andeutung, dass man das nicht verwenden sollte.
Schon, aber mit fwrite() kippst Du 'nen Sack voll Memory mit einem Funktionsaufruf in den Buffer, sonst haste für jeden char einen call samt return. Macht dann, wenn man wirklich mehr putzen mag, schon was aus.
DirkB schrieb:
Einmal überschreiben reicht : http://www.heise.de/newsticker/meldung/Sicheres-Loeschen-Einmal-ueberschreiben-genuegt-198816.html
Upps, das war mir neu. Man lernt nie aus.
-
seldon schrieb:
Mit fwrite:
real 0m0.294s user 0m0.020s sys 0m0.248s
Mit fputc:
real 0m1.259s user 0m1.016s sys 0m0.244s
Mit putc:
real 0m1.266s user 0m1.008s sys 0m0.256s
Wow, macht doch ziemlich was aus.
Zu einem Teil hängt das mit Locking zusammen - benutze ich statt putc das (linux-spezifische) _IO_putc_unlocked-Makro[...]
#define _IO_putc_unlocked(_ch,_fp) (_IO_BE ((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end, 0) \ ? __overflow (_fp, (unsigned char) (_ch)) \ : (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch)))
Auffallend ist der Test, ob der Schreibzeiger das Pufferende erreicht hat. Das kann fwrite wohl etwas besser handhaben. Trotzdem: Hast du mit Optimierung compiliert?
-
Nein, aber Optimierung macht nicht viel aus. Ergebnisse mit -O3:
fwrite:
real 0m0.261s user 0m0.016s sys 0m0.244s
fputc:
real 0m1.137s user 0m0.880s sys 0m0.256s
putc:
real 0m1.148s user 0m0.884s sys 0m0.264s
_IO_putc_unlocked:
real 0m0.486s user 0m0.300s sys 0m0.188s
-
Evtl. bringt es noch was, wenn man mit setvbuf() rumspielt.
Welche Einstellung da am meisten bringt muss man mal ausprobieren. Da wird es sicher auch einen Unterschied zwischen fputc und fwrite geben.
-
Vielen Dank für die zahlreichen Antworten!
Ich werde meinen C-Code überarbeiten und falls dann die Speicherzugriffsverletzung noch besteht melde ich mich wieder!