Autor Beitrag
trm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: 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:

ausblenden 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..22of string;
    GridCell_Eintrag: string;
    GridCell_Telefon: string;
  end;

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 480

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 403
Erhaltene Danke: 1

Winows 7
Delphi XE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19340
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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

Für diesen Beitrag haben gedankt: trm
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 480

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 25.06.10 14:35 
Sowas habe ich mir gedacht. Kann es sein, dass dein Programm auch recht langsam ist?

Probier mal soetwas:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
// globalvar:
Array_Capacity, Array_Pos: Integer;

//... Initialisierung
Array_Capacity := 1000// oder ein Schätzwert für die Anzahl der Datensätze
Array_Pos := 0// Einfüge-Poistion im Array
Setlength(GridVariables, Array_Capacity);

If Array_Pos > Array_Capacity - 1 then
begin
   Array_Capacity  := Round(Array_Capacity * 1.25); // Array um 25% vergrößern
   Setlength(GridVariables, Array_Capacity)
end 

// Daten einfügen ohne weiteres setlength
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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Sa 26.06.10 08:53 
user profile iconfreedy hat folgendes geschrieben Zum zitierten Posting springen:
Oder hast du nur sooo wenig RAM? ;-)

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:
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 :)

Für diesen Beitrag haben gedankt: trm