![]() |
Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Hallo,
es gibt hier im Forum viele Anfragen zur Fehlermeldung: Für diesen Befehl ist nicht genügend Speicher verfügbar.bzw.: Not enough storage is available to process this command.Diese sind alle älter als 5 Jahre und ich konnte auch nichts "passendes" dazu finden: Kürzlich mußte ich meine benötigte Bitmapgröße auf 8832 * 8832 Pixel erweitern. Beim Programmstart kommt nun bei manchen meiner Rechner (Windows 7, 32 Bit und Windows 10, 32 Bit) die obige Fehlermeldung. Der Trigger für die Fehlermeldung ist hier:
Code:
Bei der "Width" Zuweisung passiert es. Wenn ich das richtig berechnete habe, so würde ein 27 MiB Speicherblock benötigt. Klingt für mich nicht nach viel ...
void __fastcall CBitmapImage::Init()
{ // generate and init bitmap object Bitmap = new Graphics::TBitmap(); Bitmap->Height = Height; // 8832 pixel Bitmap->Width = Width; // 8832 pixel } noch ein paar Details:
Grüße! Michael |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Hinweis: Meiner Rechnung nach liegst du eine Zehnerpotenz zu niedrig was den Platzverbrauch angeht.
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
8832 * 8832 * 4 (32 Bit) = 312.016.896. Je nachdem wie das im Speicher liegt noch viel mehr. Irgendwas rechnest du da falsch.
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Ich hab 2,32GB als benötigte Daten-Menge, ich glaub bei 2,5GB ist mit 32bit Schluß?
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
8832 * 8832 = 78.004.224 Pixelnicht stimmen konnte dachte ich mir schon, es ergab keinen Sinn in Bezug auf den Fehler. Ich weiß darüber einfach zu wenig. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Der Speicher muss aber auch zusammenhängend frei verfügbar sein wenn er angefordert wird
insofern ist die Windows Anzeige von Freiem Speicher nicht aussagekräftig mfg Hannes |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Also meine Angabe da oben bezieht sich auf ein Standard 32bit (4 byte pro Pixel) Format, keine Eigenkreation.
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
Eventuell könntest du dein Bitmap in 4 (oder noch mehr) Quadranten einteilen und bei der Anzeige wieder zusammensetzen? Dann würde es reichen mehrere nicht-zusammenhängende kleinere Speicherblöcke zu reservieren. Und 24- bzw. sogar 32-Bit pro Pixel sind tatsächlich Standard unter Windows, also kommst du auf knapp 300MiB bei deiner Bildgröße. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
Kann per Compiler-Befehl auf 3 GB (32 Bit Windows) oder fast 4 GB (64 Bit Windows) erhöht werden. Vielleicht reicht das bei dir aus. Windows hat auch noch eine Auslagerungsdatei, womit die 4 GB physicher RAM im globaler Speicher mehr sind. Selbst bei 1 GB RAM kann ein Programm diese 2 GB nutzen (wenn genügend freier Speicher inkl. Pagefile vorhanden sind) Und wie bereits erwähnt liegt beim BITMAP der Speicher als ein zusammenhöngender Block vor und da wird es in 32 Bit-Programmen ab durchschnittlich 250-300 MB schnell eng, zwischen all den geladenen DLLs, der EXE und dem restlichen genutzten Arbeitsspeicherstückchen, sind nur selten größere Bereiche verfügbar. Im FastMM oder ![]() ![]() ![]() Die Executables (DLL/EXE) liegen nicht immer auf der selben Adressen. ![]() Und auch der restliche dynamische Speicher wird mehr "zufällig" verteilt reserviert. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Danke himitsu, von Deinen Aussagen ist die hier nach meiner derzeitigen Meinung der Knackpunkt:
Zitat:
Das Problem ist also: Ich habe im 2 GiB Virtuellen-Adressraum meines Programms öfters mal keinen zusammenhängenden Bereich von 297.5625 MiB (8832 * 8832 * 4 Bytes) übrig um meine Speicheranforderung zu bedienen. Lösungsmöglichkeit: Das Problem kann evtl. dadurch umgangen werden, das man dem Compiler mitteilt, das er 3 GiB Virtuellen-Adressraum nutzen soll. OK, ich werde sehen wie ich das hinbekomme und Melde mich dann. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Damit verschleppst du das Problem höchstens ein bisschen.
Dein Problem ist dass du Speicherfragmentierung hast. Ich kenne TBitmap zu wenig, aber vielleicht kann man den Bereich früh einmal anfordern und dann nicht mehr freigeben? Notfalls erstellst du einmal dein entsprechendes TBitmap und arbeitest immer mit dieser einen Instanz weiter. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
P.S. Eine Compiler Option für "3 GiB virtual address space" konnte ich bisher nicht finden. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Eine zuverlässige Lösungsmöglichkeit, die nicht auf irgendwelchen esoterischen Windows Speicherverwaltungs-Optionen oder Compiler-Switches basiert, habe ich weiter oben bereits genannt.
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
![]() |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Du hast 4 GB physisch und das sind meistens 6-8 GB global.
Ja, wenn da "insgesamt" weniger zur Verfügung steht, als dein Programm anfragt, dann knallt es auch. > im physischen RAM und der Auslagerungsdatei muß der Block nicht zusammenhängen (er kann auch fragmentiert dem virtuellen Block zugewiesen sein ... wird zur Laufzeit dynamisch zugewiesen/umkopiert) > in deinem privaten virtuellen Prozessspeicher ist ein Bitmap oder ein String oder ein Array immer am Stück und muß somit einem zusammenhängenden Bereich Platz finden.
Code:
Windows versucht auf Home-Systemen die Binaries (DLL/EXE) zwischen den Prozessen zu sharen und wiederverwendet vorberechnete DLLs.
**************** 16 MB RAM
* ** *** * 7 MB schon belegt ******** 9 MB sind zwar noch frei, aber ein 8 MB-Bitmap passt dennoch nicht in eine der oberen Lücken Wird eine DLL/EXE verschoben, dann muß deren Speicher angepasst werden, also überall die Adressen anpassen. Da ist es einfacher das nur einmal zu machen und dann allen Programmen die selbe angepasste DLL zu geben > nur einmal "real" Speicher, auf den alle Programme nur virtuell verweisen. (wird aber nicht dauerhaft gespeichert und ist beim Neustart erstmal weg) Spart beim Programmstart zeit, wenn die DLL schon fertig berechnet wiederverwendet wird. (OK, damals waren die Computer noch etwas langsamer und hatten weniger RAM) ![]() ![]() Auf Server-Systemen geht man davon ab (kann man auch für User-Systeme aktivieren), damit bei jedem Programm die selbe DLL nicht an der selben virtuellen Stelle liegt. Macht das blinde Hacken mit statischen Adressen nahezu unmöglich. (schwerer für Viren, Trojaner usw.) ![]() PS: Im Taskmanager gibt es mehrere Werte für den Arbeitsspeicher. "Zugesicherte Größe" ist das, was dein Programm wirklich verbraucht. und "Arbeitsspeicher (privater Arbeitssatz) dürfte das sein, was davon grade im physischen RAM liegt. (der Rest ist ausgelagert) * aktiver Speicher > das was grade im RAM liegt * reservierter Speicher > das was in deinem virtuellen Speicher belegt ist (inkl. oder exkl. gemapptem Speichers > z.B. EXE/DLL und MMF aka Memory-Mapped-Files) * und es gibt Speicher, den du reserviert hast, der aber grade nicht in deinem virtuellen Speicher gemappt ist (wird von normalen Programmen selten genutzt) * uvm. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Bei halbwegs aktuellen 64 Bit-Windowsen ist das standardmäßig schon seit Jahren aktiviert.
Zitat:
Es gab "früher" viele Programmierer, die hatten
Delphi-Quellcode:
als "ungültig" angesehn und dann teilweise in diesem Bereich sogar Zusatzinfos im Pointer gespeichert.
Integer(Pointer) <= 0
Sowas knallt, wenn Windows dem Programm plötzlich mehr als 2 GB Speicher gibt ... darum muß das im Programm erst aktiviert werden. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
3-GB und 4-GB ist quasi das Gleiche.
3-GB deshalb, weil ein 32 Bit-Windows den letzten 1 GB für Treiber und Cache nutzt und daher nicht den User-Mode-Programmen zur Verfügung stehen. In 64 Bit-Windows sind für 32 Bit Programme daher bis zu den vollen 4 GB nutzbar. (die ersten 64 KB sind aber nie nutzbar und sind immer nur Treibern vorbehalten, als Puffer für die Übergabe in den Programmspeicher) Je nach Windows-Version und verfügbaren RAM sind dann halt 3, 3.5, "ewta" 3.75 oder eben 4 GB im Programm, bzw. "physische" für alle Programme nutzbar. Tja, im 32 Bit-Windows ... k.A. wie es da in aktullen Windowsen (nach Windows 9x) aussieht, also ob schon aktiv oder nicht. Du kannst dir eine Testanwendung schreiben, die 4GB-Option aktivieren (
Delphi-Quellcode:
),
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
![]() ![]() und dann ausprobieren was überall geht. [info] Effektiv kann ein Programm in jedem 32 Bit-Windows auch über 4 GB Arbeitsspeicher verwalten. (z.B. über Pageing, MemoryMapping usw.) Ich habe hier ein kleines Testprogramm (32 Bit-Konsolenanwendung), das reserviert sich physischen Speicher und macht dir locker 100 GB RAM voll, ohne dass der Speicher ausgelagert werden kann (Pagefile). Aber das hilft dir nicht viel, da du den Speicher nicht selber verwaltest. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
Code:
Dort habe ich dann einen Breakpoint gesetzt, step over durchgeführt und Sch... der Fehler ist noch immer da. :(
...
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->HelpFile = ""; Application->CreateForm(__classid(Tfrm_MainWin), &frm_MainWin); Application->CreateForm(__classid(TfrmBitmap), &frmBitmap); Application->CreateForm(... } catch ... } Widerspricht das nicht der Annahme, das ich im 2 GiB Adressraum meines Progs. zwar genug freie Speicherbereiche habe aber halt keinen der die benötigten ca. 300 MiB hat? |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Wo ist denn dein Problem mache es doch so wie Zacherl gesagt hat teile das Bitmap in 4 oder mehr Teile auf und gut ist.
Irgendwann wirst du immer an eine grenze stoßen und dann ? Fängst wieder von vorne an. gruss |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
aber, wenn man sich schon bei Programmstart mit allem Möglichen den Speicher zumüllt, dann kann es schonmal bissl eng werden. Man kann alternativ die Forms auch erst dann "dynamisch" erzeugen, wenn man sie wirklich braucht. Aber so oder so, ab spätestens 250-300 MB gibt es immer mal Probleme, in 32 Bit-Anwendungen. (persönliche Erfahrungswerte) Die einzig sichere Lösung ist also ein Auftrennen oder Verkleinern dieses großen Blocks. (oder in einen separaten Prozess auslagen oder 64 Bit) |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Ich verstehe noch nicht was
Delphi-Quellcode:
damit zu tun hat. Kann man die Bitmap nicht vor den ganzen Formularen erstellen? Wenn man dann noch nicht einmal 300 MB am Stück hat würde ich mich allerdings auch wundern :!:
Application->CreateForm
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Für die 300 MB ist so schon kaum freier Speicher.
Wenn du vorher nun noch mehr Speicher im RAM belegst, dann erhöht sich die Chance, dass kein zusammenhängender 300 MB-Block mehr verfügbar ist. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Du könntest dir eine Prozedur schreiben die den komplett installierten (nicht nur den freien) Speicher belegt so das Windows gezwungen wird Auszulagern, nun gib den Speicher wieder frei, je nach Windows Einstellung steht Dir nun sehr viel mehr am Stück zur Verfügung oder Dll's von anderen Anwendungen laden sich selbst wieder in den schnellen Speicher, das mehr frei ist > ist ein positiver Nebeneffekt, das es Zeit kostet (auch Windows Nachladezeit, da alle Caches danach überfüllt bzw geleert sind) ist als negativer Aspekt anzusehen (Icons Fenter Text Farben alles wird neu erschaffen).
(Ziel der Übung: Memory Defrag) |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Liste der Anhänge anzeigen (Anzahl: 1)
Das ist nicht richtig.
Was Windows macht ist völlig unerheblich, Windows hat genug Puste. Eine Anwendung (z.B. Delphi) arbeitet sowieso nicht mit "echtem" Hauptspeicher sondern mit virtuellem Speicher. Das Betriebssystem (z.B. Windows) kümmert sich in Kombination mit spezieller Hardware-Beschleunigung aus der CPU um die Übersetzung von virtuellen Adressen deines Prozesses in die entsprechenden "echten" Speicheradressen. Der virtuelle Speicher ist hierbei weiterhin in Seiten unterteilt. Das Ein- und Auslagern betrifft Seiten. Es ist egal welche Seiten Windows hier ein- und auslagert, das Problem betrifft seinen privaten, virtuellen 2GB-Adressraum für seinen Prozess. Davon dass diese Seiten auch wild über den Arbeitsspeicher verteilt sein können (siehe Bild) wollen wir gar nicht erst anfangen. Viele kleine Stücke zu belegen und anschließend freizugeben verändert nicht die "Reihenfolge" in diesem Adressraum. Es wird ihm danach nicht mehr zusammenhängender Speicher zur Verfügung stehen. Viel Zeit zum Lesen? |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Ich denke, da läuft grundsätzlich was falsch bei ihm. Man nehme doch nur mal Photoshop oder Audio-Bearbeitungsprogramme, die auch schon unter 32 Bit mit großem Dateien umgehen konnten. Also ich bin ja meist der Überzeugung, wenn man an die Grenzen von Windows stößt, macht man was falsch.
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
Im Gegensatz, für das Gesamtsystem machen solche "RAM-Optimierer" das Schlimmste, was nur geht. Es wird Alles ausgelagert und anschließend muß überall wieder der aktuell genutzte Speicher wieder zurück, was somit alle Programme ausbremst. Für sowas wäre es schöner, wenn Windows eine bessere Unterstützung zur Steuerung der FileCache bietet, denn das Einzige was dieser Optimierer erreicht ist das leeren dieser Cache (der Prozessspeicher wird ja sowieso wieder zurückgeladen, sobald darauf zugegriffen wird) Wenn neuer Speicher in dem vollen physischen RAM nötig wird, dann lagert Windows schon von selber Speicher aus. (leider wird entgegen der möglichen Einstellung "Prozessspeicher zu bevorzugen" von Windows der FileCache bevorzugt, was bei großen Lese-/Schreib-/Kopieraktionen die Programme aus dem RAM verdrängt und Windows sie erst wieder laden muß, wenn sie auf ihren Speicher zugreifen wollen) Aber das Ändert rein garnichts an dem Problem mit seinem fragmentierten virtuellen Speicher. Ein PageError, weil ein Speicherblock (Page) grade nicht im RAM war, dass bekommt sein Programm garnicht mit. Es wird nur ein bisschen langsamer, aber an der Größe und Belegung seines virtuellen Speichers ändert sich nichts ... da wo die Page eingebungen ist, da bleibt sie auch. Es darf sich auch garnichts verschieben, da sonst alle Pointer ein Problem hätten, die darauf zeigen. Darum auch die Trennung zwischen Virtuellem und Physischen Speicher, damit Windows dort den realen Speicher verschieben kann wie es will, ohne dass das Programm es zu interessieren hat. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Danke an alle für Eure rege Teilnahme an meinem Problem!
Was warum auch immer mit dem TBitmap bei mir zur genannten Fehlermeldung führt kann ich nicht ergründen, denn selbst wenn die Fehlermeldung nicht kommt habe ich laut Task Manager nur 265 MiB Speicher belegt. Die Anforderungen an mein "großes Bitmap" sind hingegen bekannt und zu meinem Glück brauche ich nur das: 'Pixel ist gezeichnet oder nicht gezeichnet'. Deshalb habe ich jetzt mit
Code:
einfach ein schwarz / weiß Bitmap erstellen lassen -> Fehler ist weg und damit auch mein Problem. (Der Befehl muß vor der Zuweisung von Height and Width eingefügt werden.)
Bitmap->PixelFormat = pf1bit;
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
Wenn du in 2 GB Prozessspeicher alle 200 MB je 1 Byte speicherst, dann hast du 10 Byte belegt. OK, eigentlich 41 KB, da Windows den Speicher in 4 KB-Blöcken vewaltet. Obwohl also nur 41 KB belegt sind, hast du dennoch keine Chance dort einen freigen zusammenhängenden Block mit 300 MB zu finden. Belegt und Verwendet ist auch ein Unterschied. Du kannst 400 MB Speicher reservieren, aber wenn dort nicht reingeschrieben wurde (alles mit Nullen gefüllt), dann ist dieser Speicher nicht belegt. Wie ebenfalls schon genannt wurde, hat der Taskmanager unterschiedliche Anzeigen für "belegten" Speicher. (es gibt noch viel mehr Spalten, die man sich da anzeigen lassen kann) |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
Zum Task Manager (Windows 7): Der Wert von 265 MiB stammt vom Reiter 'Processes', Spalte 'Memory (Private Working Set)'. Eine andere Stelle kenne ich nicht, auch nicht Optionen um das zu ändern. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Alter Taskmanager (Win XP/7) im Menü Ansicht
und beim Neuen Windows 8/10 im Kontextmenü der Gridspalten. Zitat:
Werden die anderen Forms erst danach erstellt, dann verteilen sie ihren Speicher auch nicht vorher und sorgen so eventuell für ein Belegen des großen Speicherblocks. Nachher passen aber deren viele kleinen Speicherblöcke in die verbliebenen Lücken. ABER, dass bedeutet nicht, dass vorher nicht schon durch was Anderes der Speicher schon zu sehr fragentiert sein kann. z.B. neue DLLs in neueren Windowsen und dann bringen auch Zusatzprogramme, wie z.B. Drucker-, Monitor-Treiber, TeamViewer, Skype usw. ihre DLLs in alle fremden Prozesse, also auch in deine Anwendung und schwupps, schon kann es plötzlich wieder nicht mehr funktionieren, egal ob deine Forms danach sind, weil schon viele Anderes unvorhersehbar vorher abläuft. |
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Zitat:
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Es geht ja nicht darum, wieviel Speicher insgesamt zur Verfügung steht, sondern wieviel Speicher an einem Stück zur Verfügung steht. Wenn du zwar 2 Gb frei hast, aber alle 20 MB mal ein paar Byte stehen, bekommst du nie 300 MB am Stück unter. Da kannst du dich drehen und wenden soviel du willst. Dass es jetzt vielleicht funktioniert, heisst noch lange nicht, dass es dauerhaft funktioniert. Einmal Neustarten, 3-4 Programme starten und schon sieht die Speicherfragmentierung wieder ganz anders aus.
|
AW: Fehler: Für diesen Befehl ist nicht genügend Speicher verfügbar.
Es wurde ja bereits verkündet das meine Idee mit Speicher füllen falsch sei, ich habe es so getestet:
Delphi-Code:
Code:
Könnte mir bitte jemand sagen was daran falsch sei damit ich es endlich Verstehe?
procedure MyTrimWorkingSet;
var hProcess: THandle; begin hProcess := OpenProcess(PROCESS_SET_QUOTA, false, GetCurrentProcessId); try SetProcessWorkingSetSize(hProcess, $FFFFFFFF, $FFFFFFFF); finally CloseHandle(hProcess); end; end; Ist es die Funktion oder das Prinzip an sich das ich es total falsch verstehe, bin ratlos. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:03 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