Einleseroutine
-
Hallo DirkB,
danke, du hast mir die Augen geöffnet; ich habe wohl beim hastigen lesen
das "new" überlesen.Ich habe nun meine Einleseroutine fertig und wollte gerne von euch hören/
wissen, ob es nun so 'besser' ist.Nach dem Einlesen, mache ich am Ende noch ein realloc, damit ich auch wirklich
soviel Speicher verbrauche, was ich auch benötige.data2d *c_read(FILE *file, int *length) { int index = 0; size_t array_index = 0; data2d *xy = NULL; double xval, yval; while(fscanf(file, "%lf %lf", &xval, &yval) == 2) { if (index == array_index) { array_index += 1000; xy = (data2d *) realloc(xy, array_index*sizeof(data2d)); } xy[index].x = xval; xy[index].y = yval; index++; } array_index = index; xy = (data2d *) realloc(xy, array_index*sizeof(data2d)); *length = index; return xy; }
Gibt es irgendwo potentielle Memory-Leaks?
Auf eure Meinung und Kritik bin ich gespannt.
Beste Grüße,
simsa
-
Hallo,
mir wäre es sehr wichtig und wertvoll, wenn jemand mir seine Meinung äußern
würde, ob der Code Memory-Leak-Frei ist bzw. besser ist als die vorherige
'Einleseroutine' oder ob noch irgendwo potentielle Gefahren lauern.Ich möchte den Speicher optimal nutzen, weil ich anfangen muss ca. 12 TB Daten
Stück für Stück einzulesen, auswerten und wieder 'menschenlesbar' ablegen muss.Dann noch eine Frage: Der Code ist ca. drei Jahren alt. Damals wollte ich z.B.
auch wissen, wieviel Speicher der Pointer auf dem RAM belegt. Das kann man ja
mit einem Pointer nicht so einfach machen. Gibt es nun dafür 'fertige' Funktionen
in C?Beste Grüße,
simsa
-
simsa schrieb:
..., wenn jemand mir seine Meinung äußern
würde, ob der Code Memory-Leak-Frei ist bzw. besser ist als die vorherige
'Einleseroutine' oder ob noch irgendwo potentielle Gefahren lauern.DirkB schrieb:
Bedenke auch, das realloc im Fehlerfall NULL zurück gibt. Dann ist der Verweis auf deine bisherigen Daten weg und du kommst an die Daten nicht mehr ran.
simsa schrieb:
Ich möchte den Speicher optimal nutzen, weil ich anfangen muss ca. 12 TB Daten
Stück für Stück einzulesen, auswerten und wieder 'menschenlesbar' ablegen muss.Was heißt denn Stück für Stück? Wie groß ist so ein Stück?
Wieviel Daten musst du denn wirklich gleichzeitig verarbeiten?simsa schrieb:
Dann noch eine Frage: Der Code ist ca. drei Jahren alt. Damals wollte ich z.B.
auch wissen, wieviel Speicher der Pointer auf dem RAM belegt. Das kann man ja
mit einem Pointer nicht so einfach machen. Gibt es nun dafür 'fertige' Funktionen
in C?Die Größe eines Pointers gibt es mit sizeof(). Aber das ist nur die Größe des Pointers.
Du möchtest aber Informationen über den Speicher haben, auf den dieser Pointer verweist.Du kannst ja mal im Standard nachsehen. Die Links findest du auf der ersten Seite vom Unterforum unter Linkliste für Neulinge
Schau mal gleich bei C11 nach. Bis C99 gibt es das nicht.
Oder auch http://www.cplusplus.com/reference/clibrary/
-
Hallo DirkB,
danke für Deine Antwort, vorallem das mit realloc.
Nun sieht der Code wie folgt aus:
data2d *c_read(FILE *file, int *length) { int index = 0; size_t array_index = 0; data2d *xy = NULL; double xval, yval; while(fscanf(file, "%lf %lf", &xval, &yval) == 2) { if (index == array_index) { array_index += 1000; xy = (data2d *) realloc(xy, array_index*sizeof(data2d)); if (xy == NULL) { printf("\nERROR: c_read() -> realloc failure.\n"); printf("Program terminated.\n\n"); exit(EXIT_FAILURE); } } xy[index].x = xval; xy[index].y = yval; index++; } array_index = index; xy = (data2d *) realloc(xy, array_index*sizeof(data2d)); if (xy == NULL) { printf("\nERROR: c_read() -> realloc failure.\n"); printf("Program terminated.\n\n"); exit(EXIT_FAILURE); } *length = index; return xy; }
So, nun müsste alles doch so in Ordnung sein, oder sieht ihr noch wo
anders Gefahren/Lücken/Leaks?Bin echt für jeden Kommentar und Tipp sehr sehr dankbar.
Die binären Dateien sind unterschiedlich groß, z.B. von 1GB bis 50GB.
Davon habe ich soviele, dass alle zusammen ca. 12TB sind.Da ich auf Arbeit nur 8GB Arbeitsspeicher habe, hätte ich ja bei Dateien,
die kleiner sind als mein Arbeitsspeicher kein Problem. Bei den Dateien,
die größer sind als mein Arbeitsspeicher, wollte ich so vorgehen, dass ich
jeweils immer 7GB einlese, sie verarbeite und etc..., daher wollte ich
gerne wissen, ob es so eine Funktion gibt, die angibt, wie groß der Speicher
ist, worauf der Pointer zeigt. Danke für den Hinweis, ich werde mir es angucken.Beste Grüße,
simsa
-
Du musst doch eh ein Verfahren machen, das nur einen Teil der Daten im Speicher hält.
Deine Funktion
c_read
sollte kein exit machen sondern die bisherigen Daten zurückliefern und noch kenntlich machen, das noch nicht alle Daten gelesen wurden.Damit deine Daten nicht verloren gehen, musst du mit zwei Zeigern arbeiten.
So wie du es machst, gehen die Daten immer noch verloren. (Das exit löst das zwar in deinem Fall)Funktionen die das Programm im Fehlerfall beenden sind schlechter Stil.
Wieviel Daten brauchst du denn wirklich im Speicher?
Haben die ersten Datensätze noch einen Bezug zu den letzten?
Wenn 7GB von 50GB reichen, gehen dann auch 2GB oder 2MB oder 2kB?
-
Hallo DirkB,
danke für Deine schnelle Antwort.
DirkB schrieb:
Deine Funktion
c_read
sollte kein exit machen sondern die bisherigen Daten zurückliefern und noch kenntlich machen, das noch nicht alle Daten gelesen wurden.Damit deine Daten nicht verloren gehen, musst du mit zwei Zeigern arbeiten.
So wie du es machst, gehen die Daten immer noch verloren. (Das exit löst das zwar in deinem Fall)Mit zwei Pointern arbeiten? Das kenne ich beim Einlesen nicht so; wäre Dir
sehr dankbar, wenn Du mir es am Beispiel meiner 'Einleseroutine' zeigen würdest.DirkB schrieb:
Funktionen die das Programm im Fehlerfall beenden sind schlechter Stil.
Ja, das weiß ich auch. Aber, es würde meine Auswertung 'verschlechtern'. Z.B.
wenn ich nicht alle Daten eingelesen bekomme bzw. nur einen Teil, dann ist das
Ergebnis/der Mittelwert meiner Auswertung schlecht. Deswegen ist es in dieser
Hinsicht besser, das Programm zu beenden und nachdenken, warum es nicht
geklappt.DirkB schrieb:
Wieviel Daten brauchst du denn wirklich im Speicher?
Haben die ersten Datensätze noch einen Bezug zu den letzten?
Wenn 7GB von 50GB reichen, gehen dann auch 2GB oder 2MB oder 2kB?Das hängt mit der Antwort von oben zusammen. Wenn ich die 50GB in 7GB aufteile
dann habe ich zum Schluss acht Zahlen. Über diese acht Zahlen muss ich dann
wieder mitteln um nur eine Zahl zu bekommen. Wenn ich es in 2MB oder 2kB auf-
teile, dann habe ich tausende Dateien und der Mittelwert von den tausenden
Dateien wäre viel schlechter. Das habe ich schon bei einer Datei mit 4GB aus-
probiert und festgestellt, dass so der Mittelwert schlechter wird (leider).Für meine weiteren Auswertungen brauche ich den Mittelwert. Falls ich mit
einem schlechten Mittelwert weiterarbeite, dann werden meine restlichen
Auswertungen auch schlechter. Es ist leider so.Beste Grüße,
simsa
-
simsa schrieb:
Mit zwei Pointern arbeiten? Das kenne ich beim Einlesen nicht so; wäre Dir
sehr dankbar, wenn Du mir es am Beispiel meiner 'Einleseroutine' zeigen würdest.data2d *xy = NULL; data2d *tmp = NULL; double xval, yval; while(fscanf(file, "%lf %lf", &xval, &yval) == 2) { if (index == array_index) { array_index += 1000; tmp = (data2d *) realloc(xy, array_index*sizeof(data2d)); if (tmp == NULL) { // Die Daten sind hier immer noch über xy erreichbar printf("\nERROR: c_read() -> realloc failure.\n"); printf("Program terminated.\n\n"); exit(EXIT_FAILURE); } else { xy = tmp; } } xy[index].x = xval; xy[index].y = yval; index++; }
simsa schrieb:
Irgendetwas über Mittelwert
Für den arithmetischen Mittelwert braucht man nur den aktuellen Mittelwert (besser wäre die Summe der Zahlen bisher) und die Anzahl der Zahlen bisher.
Man liest die Zahlen nacheinander ein und summiert sie gleich auf.
Da musst du nicht alle Zahlen im Speicher haben.Was willst du genau berechnen?
Evtl. nutzt du den falschen Ansatz.
-
Hallo DirkB,
ich simuliere im kanonischen Ensemble Vielteilchen-Systeme mit einem Simulations-
Softwarepaket. Die Software, die ich benutze, ist eine ziemlich weit verbreiterte
Software in meinem Forschungsbereich.Aus der Software bekomme ich, wie erwähnt, binäre Dateien. Die binären Dateien
lese ich aus. Die ausgelesenen Dateien verarbeite ich dann.Nun zum:
Was willst du genau berechnen?
Also, wenn ich die Daten einlese, dann mache ich zunächst eine Fouriertrafo.
Je mehr Punkte ich habe, umso 'besser' ist die Kurve, die ich erhalte. Die
Kurve hat dann Maximas und Minimas. Ich mittele dann über die Maximas.So, wenn ich nun tausende 2MB oder 2kB Dateien habe, dann passiert es, dass
die Maximas risiege Sprünge haben, was dann mir einen 'schlechten' Mittelwert
gibt. Das liegt auch daran, dass die Rohdaten selber ziemlich verrauscht sind
aus der Simulation, aber das ist eine andere Geschichte... Wenn die Daten so
ca. 5GB bis 7GB sind, dann habe ich auch eine gute Statistik bzgl. der ein-
gelesenen Dateien, so dass die Sprünge nicht so 'krass' sind...Ich bin kein Programmier, ich habe mir das programmieren im Studium selber
beigebracht. Daher bin ich über jede Kritik und Meinung sehr dankbar, weil
ich dadurch ausschließen kann, dass keine physikalischen Fehler passieren,
falls das Ergebnis nicht so ist, wie ich es dachte. Deshalb ist mir es auch
wichtig, dass die Einleseroutine sauber funktioniert.Danke für Dein Programmcode. Das habe ich nun verstanden; aber ich habe es
lieber, wenn das Programm beendet wird, weil ich sonst keine guten 'Mittelwerte'
bekomme.Wäre dann mein Einleseroutine immernoch schlecht?
Was würde man ansonsten machen?Viele Grüße,
simsa
-
Also die Frage ist doch: brauchst du alle Daten gleichzeitig im Speicher oder nicht.
Falls ja, ist die Funktion soweit OK, bei irgendwas >4GB kann es aber u.U. zu Integer-Überläufen kommen, deshalb besser unsigned long long (ab C99) verwenden, auch ist der Blockfaktor 1000 bei diesen Größenordnungen zu klein.
U.U. hast du sowieso ein Speicherplatzproblem bei >4GB Daten und 32 Bit-Programmen.
Nehme deshalb besser einen 64-Bit Compiler.simsa schrieb:
Aus der Software bekomme ich, wie erwähnt, binäre Dateien. Die binären Dateien
lese ich aus.Mit fscanf kann man keine Binärdaten auslesen, nur char-Ströme entsprechend interpretieren.
-
Hallo Wutz,
Danke für deine Antwort.
Ja, ich brauche die Daten im Speicher; denn nach der einen 'Auswertung' kommt
dann die zweite, dritte und und und ... (im selben Programm).Kurz gesagt, ich brauche die Daten solange im Speicher, bis meine Auswertung
bzw. Programm fertig ist.Danke auch dafür, dass Du dir die Einleseroutine angeguckt hast. Ich werde
dann die meine 'Routine' (vom 13:56:14 30.06.2013) verwenden und unsigned long
long verwenden.Beste Grüße,
simsa