relocate hat geschrieben:Bedankt!
boah so einfach.
Der Wert stimmt zwar nicht ganz (die 32 Bit für die Speichervariable wird scheinbar mit zurück gegeben), aber ansonsten stimmt es.
Leider steht das weder bei Getmem https://www.freepascal.org/docs-html/rt ... etmem.html
noch auf der Übersicht (zumindest die ich gefunden habe)... https://www.freepascal.org/docs-html/rt ... tions.html
Gruß relocate
marcov hat geschrieben:An beide hinzugefügt. Korrektion sichtbar in nächster Release.
relocate hat geschrieben:Vielleicht mit der Anmerkung, dass der Rückgabewert nicht ganz dem erwartenden entspricht.
Z.B. die Puffergröße war 1024 Byte, der Rückgabewert war 1028.
Die Differenz kommt sehr wahrscheinlich von eben dem Speicherplatz für den Wert zustande.
Das mag ja somit formal richtig sein, jedoch interessiert mich dieser Wert eigentlich nicht,
denn es ist nicht die Puffergröße die nutzbar ist und eben nicht die erwartete Größe.
procedure FillZero(P: Pointer);
var i: UIntPtr;
begin
for i:=0 to MemSize(P) -1 do
PByte(P)[i] := 0;
end;
Warf hat geschrieben:Nein der wert ist schon korrekt, nur Getmem macht nicht das was du erwartest.
Warf hat geschrieben:GetMem sagt dem Betriebsystem: Hey ich brauch so viele Bytes an Speicher. Das betriebsystem gibt dann einen Pointer auf einen entsprechend großen Speicherbereich. Dabei kann das Betriebsystem vollkommen frei entscheiden wie viel Speicher es alloziiert, solange es mindestens die erwartete Größe hat.
Warf hat geschrieben:Es könnte auch direkt den gesammten Heap ausfüllen, und dir dann den pointer darauf zurückgeben. Daher sind solche funktionen wie MemSize ganz gefährlich. Es wird sogar noch lustiger, wenn du versuchst Memsize mit einem pointer der in den Stack zeigt aufzurufen bekommst du keine exception, sondern dann bekommst du MaxInt zurück.
Wenn du z.B. eine Funktion wie die hast:
- Code: Alles auswählen
procedure FillZero(P: Pointer);
var i: UIntPtr;
begin
for i:=0 to MemSize(P) -1 do
PByte(P)[i] := 0;
end;
und die mit einem Stack pointer aufrufst wird die dir schön deine gesammte memory zerstören, bis sie irgendwann eventuell mal eine exception auslöst. Das kann je nach dem in welche richtung der Stack wächst (was auch wieder dem betriebsystem und dem Compiler überlassen ist) sein das du dabei den kompletten stack, also alle Variablen, alle Rücksprungaddressen, etc. überschreibst.
Warf hat geschrieben:Außerdem kann es sein das das Betriebsystem relevante daten in diesem Overhead speichert.
Warf hat geschrieben:Langer rede kurzer Sinn, solange du keine detailierten Informationen über dein Betriebsystem hast (also z.B. bei Linux im kernel source mal vorbeischauen), und wie das den heap managed, Finger weg von MemSize
relocate hat geschrieben:Stellt sich die Frage, ist das immer so, dann kann man ja eigentlich nie den Speicher sauber verwalten. Wenn das Betriebssystem aber zurückmeldet, hey, ich habe dir so und soviel Speicher reserviert, dann ist ja alles grün. Das ist dann der Wert, den ich von Memsize erwarten würde (wenn man es weiß), es ist natürlich nicht der Wert der angefordert wurde, es ist eigentlich nicht der Wert, mit dem ich mein Programm arbeiten lassen würde, weil ich den ja nicht angefordert habe.
relocate hat geschrieben:Das würde ich aber genau so erwarten (dass Memsize dort nicht richtig arbeiten kann), in dem Fall würde ich Memsize tatsächlich nicht nutzen.
Passing an invalid pointer may lead to run-time errors (access violations).
relocate hat geschrieben:Das würde ich eher vom Speichermanager als vom Betriebssystem erwarten.
relocate hat geschrieben:Solche Klippen, die es zu umschiffen gilt, sollten ja eben angemerkt werden, dann von mir aus auch direkt bei Getmem (besser wäre das).
Warf hat geschrieben:Genau deshalb ist sowas wie MemSize in anderen Sprachen wie C nicht im Standard. Da kleine Feinheiten wie das praktisch alles kaputt machen können.
Warf hat geschrieben:Naja je nach Komplexität des Programmes kann man manchmal gar nicht wissen ob ein Pointer aus dem Stack oder dem Heap kommt. Wenn der Pointer durch verschiedene Prozeduren gejagt wird bist die Herkunft unbekannt ist hat man halt schon verloren. Man kann zwar mit ein paar tricks überprüfen ob der Pointer auf den stack zeigt, aber sobald man mehrere Threads hat, die verschiedene Stacks hat, hat man keine Chance.
Und bei dem text:Passing an invalid pointer may lead to run-time errors (access violations).
in der Dokumentation hätte ich einen Stack test irgendwie erwartet (oder zumindest einen Satz wie: does not work on stack pointers)
Warf hat geschrieben:Stimmt, habe total vergessen das Pascal ja diverse MemoryManager unterstützt (da merkt man das ich viel zu viel mit C arbeite). Da geht alles über den MM. Du könntest mal die unit cmem versuchen, damit kannst du wenigstens davon ausgehen wenn die libc die selbe ist, das dann auch der Overhead der selbe ist
Warf hat geschrieben:Ja die Dokumentation könnte besser sein (nicht das man da nicht selbst Hand anlegen könnte, meckern ist aber viel einfacher)
marcov hat geschrieben:Memory managers verwalten Speicher typisch mit eine Granularität großer als 1, zb 8 oder 16 byte. Das ist um Speicher zu sparen, mit geringere Werten werden der Administration großer dann die Ersparnisse.
relocate hat geschrieben:marcov hat geschrieben:Memory managers verwalten Speicher typisch mit eine Granularität großer als 1, zb 8 oder 16 byte. Das ist um Speicher zu sparen, mit geringere Werten werden der Administration großer dann die Ersparnisse.
Das ist ja klar. Nur ist eben die Frage, was interessiert den Programmierer, was der Memorymanager intern macht. Wenn man Memsize nicht präszise nutzen kann, sondern nur um eben festzustellen ist der Speicher groß genug, also größer gleich dem was ich speichern will oder ist er genau so groß wie ich ihn benötige sind das zwei unterschiedliche Anforderungen, wobei eine abgedeckt wird, die andere nicht, aber wie gesagt, muss man ja erst einmal wissen.
Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste