Entwickler-Ecke

Windows API - Hauptspeicher-Abfrage .


Hochhaus - Mo 30.12.13 19:30
Titel: Hauptspeicher-Abfrage .
Hallo allerseits !

ich sehe nicht, warum der folgende Code nicht funktioniert:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Var
  Form1  : TForm1;
  Memory : TMemoryStatus;

Implementation

{$R *.dfm}


Procedure TForm1.FormCreate(Sender: TObject);
Begin
 Memory.dwLength := SizeOf(Memory);
 GlobalMemoryStatus(Memory);
 Memo1.lines.Clear;
 Memo1.Lines.Add ('Memory total: ' + IntToStr(Memory.dwTotalPhys
  div 1048576) + ' MB');
 Memo1.Lines.Add ('Memory free : ' + IntToStr(Memory.dwAvailPhys
  div 1048576) + ' MB');
End;


Als Ergebnisse sehe ich immer 2047 MB ! Habe ich vergessen, etwas korrekt zu initialisieren ?
Danke für jede Antwort !

Hochhaus


jaenicke - Mo 30.12.13 20:20

Wozu die globale Variable... :roll: du benutzt sie doch nur lokal, da gibt es für so unsauberen Code doch absolut keinen Grund...

Aber zum Problem:
Wenn du die Dokumentation lesen würdest, wüsstest du wo das Problem liegt...
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366586(v=vs.85).aspx hat folgendes geschrieben:
On Intel x86 computers with more than 2 GB and less than 4 GB of memory, the GlobalMemoryStatus function will always return 2 GB in the dwTotalPhys member of the MEMORYSTATUS structure. Similarly, if the total available memory is between 2 and 4 GB, the dwAvailPhys member of the MEMORYSTATUS structure will be rounded down to 2 GB.
Und als Lösung:
Zitat:
applications should use the GlobalMemoryStatusEx [http://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx] function instead


// EDIT:
Sprich korrekt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.FormCreate(Sender: TObject);
var
  Memory: TMemoryStatusEx;
begin
  Memory.dwLength := SizeOf(Memory);
  if GlobalMemoryStatusEx(Memory) <> 0 then
  begin
    Memo1.Lines.Clear;
    Memo1.Lines.Add('Memory total: ' + IntToStr(Memory.ullTotalPhys div 1048576) + ' MB');
    Memo1.Lines.Add('Memory free : ' + IntToStr(Memory.ullAvailPhys div 1048576) + ' MB');
  end
  else
    Memo1.Text := SysErrorMessage(GetLastError);
end;


Hochhaus - Mo 30.12.13 20:36

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:

// EDIT:
Sprich korrekt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.FormCreate(Sender: TObject);
var
  Memory: TMemoryStatusEx;
begin
  Memory.dwLength := SizeOf(Memory);
  if GlobalMemoryStatusEx(Memory) <> 0 then
  begin
    Memo1.Lines.Clear;
    Memo1.Lines.Add('Memory total: ' + IntToStr(Memory.ullTotalPhys div 1048576) + ' MB');
    Memo1.Lines.Add('Memory free : ' + IntToStr(Memory.ullAvailPhys div 1048576) + ' MB');
  end
  else
    Memo1.Text := SysErrorMessage(GetLastError);
end;


Das habe ich schon probiert . . . der Compiler quittiert dies mit der Fehlermeldung -->
[Fehler] UNIT1.PAS(39): Undefinierter Bezeichner: 'TMemoryStatusEx'

Hochhaus


FinnO - Mo 30.12.13 20:41

Moin,

versuch doch den TMemoryStatusEx-Struct (als Record) selbst zu bauen:

Siehe Doku:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type
 DWORDLONG = Int64; // ULONGLONG
type
  PMemoryStatusEx = ^TMemoryStatusEx;
  LPMEMORYSTATUSEX = PMemoryStatusEx;
  {$EXTERNALSYM LPMEMORYSTATUSEX}
  _MEMORYSTATUSEX = packed record
    dwLength : DWORD;
    dwMemoryLoad : DWORD;
    ullTotalPhys : DWORDLONG;
    ullAvailPhys : DWORDLONG;
    ullTotalPageFile: DWORDLONG;
    ullAvailPageFile: DWORDLONG;
    ullTotalVirtual : DWORDLONG;
    ullAvailVirtual : DWORDLONG;
  end;
  {$EXTERNALSYM _MEMORYSTATUSEX}
  TMemoryStatusEx = _MEMORYSTATUSEX;
  MEMORYSTATUSEX = _MEMORYSTATUSEX;
  {$EXTERNALSYM MEMORYSTATUSEX}
[1] [http://www.delphipraxis.net/93132-globalmemorystatus-bz-w-globalmemorystatusex.html]

Gruß


jaenicke - Mo 30.12.13 20:41

Dann kennt deine Delphiversion den Typ noch nicht, den brauchst du ja nur aus der Dokumentation abschreiben...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
type
  TMemoryStatusEx = record
    dwLength: DWORD;
    dwMemoryLoad: DWORD;
    ullTotalPhys: UInt64;
    ullAvailPhys: UInt64;
    ullTotalPageFile: UInt64;
    ullAvailPageFile: UInt64;
    ullTotalVirtual: UInt64;
    ullAvailVirtual: UInt64;
    ullAvailExtendedVirtual: UInt64;
  end;

function GlobalMemoryStatusEx(var lpBuffer : TMemoryStatusEx): BOOL; stdcallexternal kernel32 name 'GlobalMemoryStatusEx';
//EDIT:
ok, ein paar Sekunden zu spät...

// EDIT2:
Ach ja, bei mir ist die Definition (so ähnlich) in der Unit Windows drin.


Hochhaus - Mo 30.12.13 20:49

... Der Compiler reklamiert beim Typ UInt64 ... Offenbar muss ich Delphi 6 PE definitiv beerdigen.

Hochhaus


jaenicke - Mo 30.12.13 20:51

Nimm Int64... da dort keine negativen Werte vorkommen und der RAM auch nicht so groß sein kann, dass die Grenzen von Int64 erreicht werden, sollte das auch gehen.

// EDIT:
Da bei dir im Profil Delphi XE2 steht, verstehe ich allerdings ohnehin nicht so recht was du noch mit Delphi 6 machst... ;-)


Hochhaus - Mo 30.12.13 21:00

[quote="user profile iconjaenicke"(682779)
Da bei dir im Profil Delphi XE2 steht, verstehe ich allerdings ohnehin nicht so recht was du noch mit Delphi 6 machst... ;-)[/quote]

... Programme für ältere OS wie Win2000 ...

Scherz beiseite: Jetzt kompiliert das Programm fehlerfrei, und liefert mir zufällige Werte für den Speicher (siehe Beilage Memory.jpg)


jaenicke - Mo 30.12.13 21:50

user profile iconHochhaus hat folgendes geschrieben Zum zitierten Posting springen:
Scherz beiseite: Jetzt kompiliert das Programm fehlerfrei, und liefert mir zufällige Werte für den Speicher (siehe Beilage Memory.jpg)
Vergleich doch einmal mit dem Taskmanager. Wenn du ein 32-Bit Betriebssystem hast, sehen die doch korrekt aus...


Hochhaus - Di 31.12.13 02:28

Ok. Ich habe ein 32-Bit-System. Aber warum ist das korrekt ? Ich habe doch 4 GB Speicher ...! Kann der Prozessor die in diesem Fall nicht komplett adressieren ?


Hochaus

P.S. In den Windows-Systeminformationen kommen 4 GB vor.

Aber Du hast recht: Im Taskmanager sind die Zahlen dieselben. Nur unter "Installiert" kommt 4 GB.


Delete - Di 31.12.13 09:51

Das Grafik-ROM wird immer in den oberen RAM-Bereich geladen.
Bei nicht-dedizierten Grafikkarten liegt auch der Grafikspeicher im RAM.
Was dann übrig bleibt, ist das "Memory total".

Shared-Memory-Technologie bei Grafikkarten
http://de.wikipedia.org/wiki/Grafikkarte
http://de.wikipedia.org/wiki/Shared_Memory
http://de.wikipedia.org/wiki/Intel_GMA
http://de.wikipedia.org/wiki/Unified_Memory_Architecture


jaenicke - Di 31.12.13 10:02

user profile iconHochhaus hat folgendes geschrieben Zum zitierten Posting springen:
Ok. Ich habe ein 32-Bit-System. Aber warum ist das korrekt ? Ich habe doch 4 GB Speicher ...! Kann der Prozessor die in diesem Fall nicht komplett adressieren ?
Richtig.

user profile iconhathor hat folgendes geschrieben Zum zitierten Posting springen:
Das Grafik-ROM wird immer in den oberen RAM-Bereich geladen.
Was dann übrig bleibt, ist das "Memory total".
Das hat bei einem 32-Bit Betriebssystem damit nichts zu tun, das kann so oder so nicht die ganzen 4 GiB adressieren.


Hochhaus - Di 31.12.13 11:51

Ok. Wieder etwas dazugelernt. Wie ich gesehen habe, wird auf meinem Notebook - mit 64 Bit-Betriebssystem - der ganze Speicher von 8 GB erkannt und angegeben. Ich verwende als Desktop einen Core-2-Duo mit 2.83 GHz von HP Compaq - und als Notebook einen HP mit Core-I7-Prozessor bei 2.2 GHz. Auf beiden läuft Win7 - einmal 32 Bit und einmal 64 Bit.


Hochhaus

Nachtrag: Offenbar ist eine Graphikkarte mit eigenem RAM von Vorteil ...


jaenicke - Di 31.12.13 12:03

user profile iconHochhaus hat folgendes geschrieben Zum zitierten Posting springen:
Nachtrag: Offenbar ist eine Graphikkarte mit eigenem RAM von Vorteil ...
Das sowieso, einerseits ist das viel schneller (abgesehen von integrierten APUs, die sind auch recht schnell) und andererseits steht entsprechend mehr RAM zur Verfügung, wenn der nicht durch die Grafikkarte benutzt wird.
Bei einem 32-Bit Betriebssystem kann die Grafikkarte aber unter Umständen den RAM nutzen, der von Windows ohnehin nicht genutzt werden kann, wenn man mehr als den nutzbaren RAM hat.


Hochhaus - Di 31.12.13 12:14

Noch eine Frage: Wieviel RAM genau kann ein 32-Bit-Betriebssystem maximal adressieren ? 2 hoch 32 Bit ?

Hochhaus

In dem Falle wäre der Adressbereich eines 64-Bit-Systems aber gewaltig und kann wohl nie verwendet werden .


jaenicke - Di 31.12.13 13:44

Adressieren könnte man die 4 GiB, ja. Maximal nutzbar ohne PAE [http://de.wikipedia.org/wiki/Physical_Address_Extension] sind etwa die 3,5 GiB, die du dort auch stehen hast.

Bei 64-Bit Betriebssystemen hat man höhere Grenzen, aber trotzdem ist es nicht so viel wie es zunächst scheint. Windows 7 Home Premium unterstützt 16 GiB, ab der Pro sind es 192 GiB, Windows 8 Professional kann 512 GiB und Server 2012 Standard z.B. 4 TiB. Das sind aber alles Softwarelimits.

Und da es heute schon Serversysteme mit hunderten GiB RAM gibt, glaube ich nicht, dass die 64-Bit Grenze nie erreicht wird. ;-)


Xion - Di 31.12.13 13:54

user profile iconHochhaus hat folgendes geschrieben Zum zitierten Posting springen:
Noch eine Frage: Wieviel RAM genau kann ein 32-Bit-Betriebssystem maximal adressieren ? 2 hoch 32 Bit ?

Nicht bit, sondern Byte! Du kannst deinen Speicher nicht bit-adressieren. Es sind also 2^32 Byte maximal (mit Einschränkungen, siehe vorherigen Post).


Hochhaus - Di 31.12.13 13:58

Ich glaube auch, dass 2^64 Byte sehr lange ausreichen werden. Aber in der Tat: Als man vor 30 Jahren MS-DOS erfand, glaubte man, dass ein 16-Bit OS längstens ausreicht. Und heute sind 32 Bit nicht mehr genug. Daher kann man nicht wissen, was bis in weiteren 30 Jahren passiert .. Vielleicht gibt es dann Licht- und/oder Quantencomputer.


Delete - Di 31.12.13 15:49

Nur mal so am Rande:

Ich könnte mir vorstellen, dass es bald bildgebende Ultraschallgeräte mit WLAN (nicht größer als ein Wasserglas) für den "Hausgebrauch" gibt.
Einfache US-Geräte gibt es schon, die können z.Zt. aber nur den Herzschlag des Kindes im Uterus detektieren und in Schall umwandeln.
Wenn man aber ein 3D-Bild vom gleichen Objekt haben will, braucht man schon ein bisschen mehr "Rechenpower".

Einsatzgebiet: DoItYourself Vorsorgeuntersuchungen zuhause:
- von den Brüsten - Jede achte bis zehnte Frau erkrankt im Laufe ihres Lebens an Brustkrebs.
- von der Aorta (Aneurysma) und anderen Arterien, z.B. am Hals und im Oberschenkel (Stenosen)
- vom Herzen
- innere Organe


drstar - So 17.04.16 18:26

user profile iconHochhaus hat folgendes geschrieben Zum zitierten Posting springen:
Ok. Ich habe ein 32-Bit-System. Aber warum ist das korrekt ? Ich habe doch 4 GB Speicher ...! Kann der Prozessor die in diesem Fall nicht komplett adressieren ?


Hochaus
[...]



Nun, es muß zwischen Betriebssystem und Anwendung unterschieden werden. Bei x86-32 kann das OS max. 4 GByte verwalten (2^32 Byte), dabei stehen je nach Hardware jedoch nur 3,25 bis 3,5 GByte effektiv zur Verfügung. Bei der 32-Bit-Architektur kann eine Anwendung jedoch nur max. 2 GByte nutzen, und genau diese 2047 MByte bekommst Du ja auch angezeigt.