![]() |
Frage zu Out of Memory Error (Ältere Delphi Version)
Hi,
Ich habe folgenden einfachen Code den ich in Delphi (Windows) ausführe: var i : Integer; anArray : Array of String; for i := 0 to 1000000 do begin setLength(anArray, length(anArray) + 1); anArray[length(anArray) - 1] := intToStr(random(100000000)); end; Ich frage mich nun, wieso das in einem Out of Memory (Zu wenig Arbeitsspeicher) endet. Würde Ich stattdessen das array nur einmal auf die Größe 1000000 setzen, gäbe es erstmal keinen solchen Fehler (Das ist aber nicht die gesuchte Lösung hier). |
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Hallo,
bei mir läuft Dein Code ohne jedwede Fehlermeldung. Vielleicht liegt die Ursache außerhalb der obigen Schleife (verschleppter Fehler, nicht freigegebene dynamische Arrays?) |
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Sorgt nicht ein SetLength dafür das erst Platz für neue größe (durchgehender Adressraum) geschaffen wird und dann das alte Array dorthin kopiert wird?
D.h. du brauchst auf jedenfall mehr RAM als wenn du direkt die maximale Zielgröße anforderst. Das zusammen mit den sehr einfach gestrickten MemoryManager von alten Delphis (hier war FastMM4 ein absolute Notwendigkeit) ist das Problem zu erklären. |
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Der Fehler tritt definitiv in diesem Code auf, also es liegt nicht an Code der davor ausgeführt werden würde (
![]() Es ist gut möglich (und hoffentlich der fall), dass es in neueren Delphi Versionen nicht mehr zu diesem Fehler kommt. Ich nehme an, in einer älteren Version habe Ich dann keine andere Alternative, als auf zu häufiges ändern der Array Größe zu verzichten? |
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Welche Delphi-Version verwendest Du?
Zitat:
|
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Eventuell genügt es, einmal dem Array eine maximale Größe zuzuweisen und dann nur noch kleinere Werte (aber größer als 0) zu setzen. Aber ich kann aktuell auch nicht sagen, ob das in Delphi 7 was bewirkt.
Im Array werden ja auch nur die Pointer auf die Strings gespeichert, die natürlich auch dynamischen Speicherbereich benötigen. Ich vermute, dass dies zu einer Zerstückelung des Speichers führt, bei der dann irgendwann keine großen Blöcke mehr verfügbar sind. |
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Zitat:
|
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Ich möchte Sebastian ausdrücklich beipflichten! :thumb:
Seit Delphi 5 verwende ich einen ähnlichen Trick bei der Nullstellen-Suche von Funktionen mit sehr vielen Nullstellen: z. B. Bessel-Funktionen bei der instationären Wärmeübertragung, die je nach Anwendungsfall zwischen 0 und tausenden Lösungen haben können. Um nicht bei jeder neuen Nullstelle das Array mit den Lösungen neu dimensionieren (und intern den Inhalt u. U. stets umkopieren) zu müssen, mach ich z. B. 50-er Sprünge bei
Delphi-Quellcode:
. Das ist deutlich schneller und verhindert die noch schlimmere Fragmentierung des Heap. :-D
SetLength(..)
|
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Ja, Arrays sind immer zusammenhängend im Speicher.
Bei mehrdimensionalen dynamischen Arrays betrifft das jede Ebene/ParentLevel einzeln. (statische Arrays sind auch über alle Level immer zusammenhängend) Und ja, wenn das Array der Speicher vergrößert wird, wird jeweils eine völlig neue Kopie erstellt, also neuer Speicher, Inhalt rüberkopieren und das alte Freigeben. Ich glaube auch das SetLength wurde später nochmal etwas verbessert, so dass es größere Bereiche neu reservert und dann die nächsten paar Durchläufe nichts machen muß. Und natürlich der optimalere Speichermanager, aber bei größeren Blöcken gibt es zwischen altem und neuem Manager praktisch keine Unterschiede. |
AW: Frage zu Out of Memory Error (Ältere Delphi Version)
Unabhängig davon, dass dieses Vorgehen eh bestraft gehört (was die Speicherverwaltung hier übernimmt)
ist es einfach nur schwachsinnig so oft nutzlos den Speichermanager zu beschäftigen. Du hast also gleichzeitig 1-2 große Speicherblöcke (das Array), eine Masse an kleinen Speicherblöcken (die vielen Strings) und zussätzlich noch im Speicher verteilt anderes Zeugs, wie die EXE, DLLs usw. Wie im alten DelphiMM Speicher verteilt ist ... tja, könnte man mal nachsehn. ![]() Im aktuellen FastMM ist kleiner und großer Speicher bestimmt aus diesem Grunde möglichst voneinander getrennt. PS: Die 4-GB-Option (LargeAddressAware) ist auch im alten Delphi nutzbar, aber es ist nicht wirklich die Lösung, denn das Array ist eigentlich bloß 1000000*SizeOf(Integer)+8 * 2 groß, also lediglich 4 und kurzzeitig 8 MB. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz