| Autor |
Beitrag |
trm
      
Beiträge: 491
Erhaltene Danke: 19
Windows 7x64
Delphi 7
|
Verfasst: Fr 25.06.10 10:00
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
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Fr 25.06.10 10:34
Wie vergrößerst du das Array, bzw. wie oft rufst du Setlength auf?
_________________ We are, we were and will not be.
Für diesen Beitrag haben gedankt: trm
|
|
freedy
      
Beiträge: 403
Erhaltene Danke: 1
Winows 7
Delphi XE
|
Verfasst: 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
Für diesen Beitrag haben gedankt: trm
|
|
trm 
      
Beiträge: 491
Erhaltene Danke: 19
Windows 7x64
Delphi 7
|
Verfasst: 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: www.nogad.de/nogad/i...amp;TRM=BESTELLBUCH3
|
|
jaenicke
      
Beiträge: 19340
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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. 
Für diesen Beitrag haben gedankt: trm
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: 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. 
_________________ We are, we were and will not be.
Für diesen Beitrag haben gedankt: trm
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: 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.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Für diesen Beitrag haben gedankt: trm
|
|
trm 
      
Beiträge: 491
Erhaltene Danke: 19
Windows 7x64
Delphi 7
|
Verfasst: 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 
      
Beiträge: 491
Erhaltene Danke: 19
Windows 7x64
Delphi 7
|
Verfasst: 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
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 26.06.10 08:53
Für diesen Beitrag haben gedankt: trm
|
|
|