WinAPI GlobalAlloc vs. LocalAlloc

ManicMarble

Erfahrenes Mitglied
Guten Abend zusammen,
ich hätte mal eine grundsätzliche Verständnisfrage zur Windows API. Ich programmiere zwar in diesem Fall nicht mit C/C++, aber ich schätze mal, hier sind die meisten Leute versammelt, die sich mit der Windows Speicherverwaltung besser auskennen als ich.

Ich schreibe eine DLL, die große Blöcke an Speicher alloziiert, vollschreibt und wieder freigibt. Ich habe dazu in meiner API-Bibel nachgelesen und zunächst GlobalAlloc/GlobalFree verwendet. Ich habe eine kleine Test-DLL geschrieben und deren Treiben mit einem Memory-Monitor beobachtet. Es hat sich gezeigt, dass GlobalFree offensichtlich den Speicher nicht wieder freigibt, zumindest nicht sofort!

Die Test-App. läuft auf einem Win'98-System mit 512MB RAM und 1,7GB verfügbarem virtuellem Speicher. Ich schreibe 50 Millionen DWORDs in einen vorher hierfür mit GlobalAlloc alloziierten Speicherblock (200.000.000 Byte), danach gebe ich diesen mit GlobalFree wieder frei. Das Ganze mache ich 5 mal, dann ist der virtuelle Speicher runter auf unter 10MB. Beim 6. Durchgang schmiert dann logischerweise die Anwendung ab. Im Memory-Monitor kann man das wunderbar mitverfolgen.

Habe dann das alles umgeschrieben auf LocalAlloc/LocalFree. Jetzt kann ich dieses Spiel treiben so oft ich will. Im Memory-Monitor sieht man auch schön, wie der Speicher belegt und wieder freigegeben wird. Alles wunderbar.

Nun steht aber in meinem API-Buch: "Die durch GlobalAlloc() und LocalAlloc() alloziierten Speicherbereiche sind in der linearen 32bit-Umgebung von Win32 gleich." Das kann ja demnach so nicht stimmen, oder?

Was genau ist denn nun der Unterschied zwischen globalem und lokalem Speicher. Und was genau ist der "private Heap"? Was ist der beste Ort, um so große Speicherobjekte abzulegen? Die Daten müssen nicht von außerhalb der DLL erreichbar sein.

Über ein bischen Nachhilfe für einen echten Stümper in Sachen Speicherverwaltung würde ich mich sehr freuen.

Viele Grüße,
Martin
 
Da kann tatsächlich etwas nicht stimmen, denn meine MSDN sagt:
The local heap for each process cannot exceed 1 megabyte. However, a process can create multiple heaps using the HeapCreate function and each of these heaps can be up to 1 megabyte.
 
Witzig, den Satz von jokey2 hab ich in meiner MSDN nicht stehen, dafür aber das:

Windows Me/98/95: The heap managers are designed for memory blocks smaller than four megabytes. If you expect your memory blocks to be larger than one or two megabytes, you can avoid significant performance degradation by using the VirtualAlloc or VirtualAllocEx function instead.


Du müsstest doch auch einfach new benutzen können, um deine dicken Speicherblöcke zu belegen?
 
"new benutzen"...? Ähhh, aha. Wo krieg' ich denn so ein "new" her, damit ich's benutzen kann... :) (Mit anderen Worten: Verstehe nur Bahnhof).

Wie gesagt, meine DLL funktioniert jetzt tadellos mit LocalAlloc/LocalFree, ich weiß nur eben nicht, wieso sie mit GlobalAlloc/GlobalFree nicht funktioniert. Meine API-Bibel sagt, Global- und LocalAlloc seien das selbe und dann gäbe es noch den "privaten Heap". Und den "virtuellen Speicher", das entspräche der Auslagerungsdatei.
Was genau ist das denn das nun alles? Dem API-Buch traue ich nicht mehr so recht (zumal ich da mal was von "Windows 94" gelesen hab ;)).

Das was ich gelesen habe verstehe ich so, dass VirtualAlloc ausschließlich die (langsame) Auslagerungsdatei, also grundsätzlich die Festplatte benutzt. Natürlich ist es so, dass ich bei sooo riesigen Blöcken auf jedenfall irgendwann im virtuellen Speicher lande. Allerdings werden im "richtigen Leben" nur selten so gigantische Datenmengen benötigt, in der Test-DLL simuliere ich eben den Extremfall, später möchte ich eigentlich nicht grundsätzlich immer in den virtuellen Speicher. Nur: Wenn der reservierte Speicher nicht mehr freigegeben wird wie in meinem Fall mit GlobalFree, dann führt das auch bei vielen Operationen mit kleinen Blöcken irgendwann zum Crash.

Wie gesagt, bin kein Speicherverwaltungsprofi und mir hat den Kram eben noch nie jemand wirklich richtig erklärt.
 
Wie eingangs erwähnt: Ich mach' das nicht in C/C++.
Was ich brauche (für die aufrufende App.) ist ein zusammenhängender Block von DWORDs.
 
Sorry, das kein C/C++ hatte ich überlesen.
Also eigentlich sollte GlobalFree das direkt freigeben. Hast du irgendwelche Flags übergeben? (GMEM_FIXED zum Beispiel).
Und selbst wenn der Speicher voll wird, sollte das nicht abstürzen, sondern GlobalAlloc einfach NULL zurückgeben.
 
Als Flags übergebe ich GMEM_MOVEABLE und GMEM_ZEROINIT - bzw. jetzt eben LMEM_MOVEABLE und LMEM_ZEROINIT (wobei: das sind ja die selben Werte).

Und die Aufrufende Anwendung (Toolbook) stürzt tatsächlich ab. Das tut sie aber auch, wenn ich LocalAlloc verwende und den Speicher vollschreibe ohne freizugeben (mit GlobalAlloc wie gesagt auch Absturz trotz freigeben).

Um den unkontrollierten Absturz zu verhindern, schaue ich jetzt vor LocalAlloc() mit GlobalMemoryStatus() nach, ob genügend Platz da ist, wobei ich hier allerdings auch nicht verstehe, waum ich da nun ausgerechnet den Wert dwAvailPageFile hernehmen muss.
 
Zurück