Entwickler-Ecke
Sonstiges (Delphi) - Array of record-type erzeugt Out of memory
trm - Fr 25.06.10 10:00
Titel: Array of record-type erzeugt Out of memory
Hi.
Ich habe mal wieder ein komisches Problem.
Folgenden Type deklariere ich für ein komplettes Projekt als global:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| type T_GridVariables = record NewDay_Caption: string; NewDay_Date:String; NewDay_Grid_Name:Integer; GridCell_Uhrzeit: string; GridCell_Nummer: string; GridCell_Name: string; GridCell_X1: string; GridCell_Bemerkung: string; GridCell_X2: string; GridCell_Geburtsdatum: string; GridCell_User: string; GridCell_Lock: Boolean; GridCell_Einweiser: string; GridCell_FreiesFeld: array[11..22] of string; GridCell_Eintrag: string; GridCell_Telefon: string; end; |
Delphi-Quelltext
1: 2:
| var GridVariables: array of T_GridVariables; |
Zugreifen kann ich von überall aus, das Array wird dynamisch in der Größe angepasst (setlength).
Wenn nun aber das Array of T_GridVariables die Größe von 17572 erreicht hat, gibt es ein Out of Memory (Windows XP, SP3 (2GB RAM), Windows 7x64 (4GB RAM)).
Als Delphi nutze ich Delphi 7, SP1.
Was kann ich tun, damit der Fehler nicht auftritt?
Gruß
~M.
Gausi - Fr 25.06.10 10:34
Wie vergrößerst du das Array, bzw. wie oft rufst du Setlength auf?
freedy - Fr 25.06.10 10:40
Hallo trm,
ich habe gerade mal probiert, das nachzuvollziehen. Ich kann das Array beliebig vergrößern. 100000 Einträge waren gar kein Problem. Was machst du denn sonst noch? Oder hast du nur sooo wenig RAM? ;-)
Grüße
trm - Fr 25.06.10 13:59
Hallo ihr beiden.
Danke für die Antwort.
Hier der Teil, mit dem ich das Array jedesmal neu setze:
Delphi-Quelltext
1: 2:
| inc(Array_Count, 1); Setlength(GridVariables, Array_Count); |
Ich lese aus einer Datenbank, die kein sql unterstützt (TDbf -> SourceForge) Einträge und bereite diese für HTML/Excel/csv auf. Daher auch das Array-Record.
Sobald passende Daten gefunden werden, wird das Array um eins erhöht.
Ich nutze hier Windows 7x64 (4 GB RAM) mit Delphi 7 SP1
Auf einem anderen (physischen) Rechner: Windows XP, SP3, 2 GB RAM tritt aber der Fehler ebenso auf.
Es geht um dieses Programm:
http://www.nogad.de/nogad/index.php?&TRM=BESTELLBUCH3
jaenicke - Fr 25.06.10 14:29
Vergrößere Das Array immer um 100 Datensätze oder so und schreibe die dann voll, dann wirst du deutlich mehr Geschwindigkeit haben.
Ob der Fehler daraus resultiert, weiß ich nicht, aber eigentlich sollte das nicht der Fall sein. Da vermute ich eher ein Speicherproblem. Am besten aktiviere einmal die Bereichsüberprüfung in den Projektoptionen unter Compiler und erzeuge das Projekt neu. Wenn dann davon eine Fehlermeldung kommt, hast du ein Problem oder vielmehr einen Bug drin. :D
Gausi - Fr 25.06.10 14:35
Sowas habe ich mir gedacht. Kann es sein, dass dein Programm auch recht langsam ist?
Probier mal soetwas:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| Array_Capacity, Array_Pos: Integer;
Array_Capacity := 1000; Array_Pos := 0; Setlength(GridVariables, Array_Capacity);
If Array_Pos > Array_Capacity - 1 then begin Array_Capacity := Round(Array_Capacity * 1.25); Setlength(GridVariables, Array_Capacity) end
GridVariables[Array_Pos] := ...; inc(Array_Pos); |
Durch dein ständiges Vergrößern des Arrays geht viel Platz verloren, da ständig neuer Speicher reserviert werden muss, um das neue Array unterzubringen. Es ist daher sinnvoll, dass Array in größeren Schritten zu vergrößern und sich in einer Hilfsvariable zu merken, wie viel schon belegt ist.
So macht das übrigens auch TObjectList, die du dir evtl. auch mal ansehen solltest. Dann musst du zwar mit TObject anstelle von Records arbeiten, aber diese Klasse nimmt einem in der hinsicht viel Arbeit ab. ;-)
BenBE - Fr 25.06.10 15:08
Also ich würde auch als Programm mich weigern:
Dein Record-Typ ist 112 Bytes groß (grad mal kurz überschlagen anhand der Definition; SizeOf könnte abweichen).
Rechnen wir also mal kurz:
112 Bytes/Eintrag * 17572 Einträge = 1968064 Bytes = 1,88 MiB
(Da stehen noch keine Daten in den Strings drinnen)
Da du aber durch die zahlreichen Speicher-Realloziierungen den Speichermanager vollständig aus dem Tritt bringst, findet der keinen Block in dieser größe mehr und weigert sich folglich ...
Wie schon von den Vorrednern gesagt: Fordere den Speicher in wesentlich größeren Blöcken an und merke Dir, bis wohin Du dein Array befüllt hast. Das geht um einiges schneller UND fragmentiert den Speichermanager (Heap) nicht so stark.
trm - Fr 25.06.10 18:44
Danke Euch allen, die mir helfen :)
Tja, das ist eben das Problem bei einem Hobby. Man hat es normalerweise nicht gelernt ;)
Tatsächlich ist das Programm bei einigen Operationen SEHR langsam.
Daher werde ich nachher Eure Hinweise umsetzen. Ich berichte dann später nochmal vom Ergebnis.
Ihr seid super :)
Viele Grüße, bis später
~Mathias
trm - Fr 25.06.10 21:37
So, bin soweit, dass ich nochmal ein GROßES DANKESCHöN an Euch lieben Helfer geben möchte.
Der Speicherfehler kommt nun nicht mehr :)
Bis zum nächsten Fehler meinerseits wünsche ich Euch allen ein schönes Wochenende :)
Viele Grüße
~Mathias.
delfiphan - Sa 26.06.10 08:53
freedy hat folgendes geschrieben : |
| Oder hast du nur sooo wenig RAM? ;-) |
trm hat folgendes geschrieben : |
Ich nutze hier Windows 7x64 (4 GB RAM) mit Delphi 7 SP1
Auf einem anderen (physischen) Rechner: Windows XP, SP3, 2 GB RAM tritt aber der Fehler ebenso auf. |
FYI. Es ist völlig egal, wieviel RAM installiert ist. Das Problem ist der Virtual Address Space, der wohl so fragmentiert ist, dass kein zusammenhängendes, grosses Stück mehr gefunden werden kann. Virtual Address Space <> Virtual Memory <> Physical Memory
Mit Windows 7x64 kannst du den Virtual Address Space für 32-bit Programme verdoppeln, indem du {$SetPEFlags $20} als Flag in den Source schreibst. Das ist aber natürlich nicht die Lösung zum Problem. Das Design hast du ja mittlerweile aber verbessert :)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!