Abfangen von Speicherüberlauf
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Abfangen von Speicherüberlauf
Hallo,
habe wieder mal ein Problem.
Ich will einem Pointer einen großen Speicherbereich zuordnen mit getmem (etwa 500 MB, nämlich eine ganze Datei laden). Aber wenn der Speicher schon zu voll ist, dann gibt es da Access Violation. Wie läßt sich so etwas abfangen? (D.h. wie kann ich die maximal mögliche Speichergröße für die Zeigervariable feststellen?)
Leider gibt es ja nicht mehr die Funktion maxavail bzw memavail wie in Turbo Pascal, die einem sagte, wieviel Platz noch übrig bzw möglich ist.
Ginge das mit try .. except.. oder ähnlich? Könnte mir jemand einen Code dazu schreiben?
Herzlichen Dank.
habe wieder mal ein Problem.
Ich will einem Pointer einen großen Speicherbereich zuordnen mit getmem (etwa 500 MB, nämlich eine ganze Datei laden). Aber wenn der Speicher schon zu voll ist, dann gibt es da Access Violation. Wie läßt sich so etwas abfangen? (D.h. wie kann ich die maximal mögliche Speichergröße für die Zeigervariable feststellen?)
Leider gibt es ja nicht mehr die Funktion maxavail bzw memavail wie in Turbo Pascal, die einem sagte, wieviel Platz noch übrig bzw möglich ist.
Ginge das mit try .. except.. oder ähnlich? Könnte mir jemand einen Code dazu schreiben?
Herzlichen Dank.
- m.fuchs
- Lazarusforum e. V.
- Beiträge: 2822
- Registriert: Fr 22. Sep 2006, 19:32
- OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
- CPU-Target: x86, x64, arm
- Wohnort: Berlin
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Der mögliche Platz wäre auch schwer zu ermitteln und nützt dir nichts. Er kann ja zwischen Ermitteln und Reservieren bereits wieder belegt werden.
Aber zumindest den Fehler kannst du abfangen. Es gibt eine Varable namens ReturnNilIfGrowHeapFails. Wird diese auf True gesetzt (Standard ist False) dann gibt es keinen Fehler wenn der Speicher nicht ausreicht. Stattdessen wird einfach nil in den Pointer geschrieben. Und das kann man dann für seien Zwecke auswerten:
hth
Michael
Aber zumindest den Fehler kannst du abfangen. Es gibt eine Varable namens ReturnNilIfGrowHeapFails. Wird diese auf True gesetzt (Standard ist False) dann gibt es keinen Fehler wenn der Speicher nicht ausreicht. Stattdessen wird einfach nil in den Pointer geschrieben. Und das kann man dann für seien Zwecke auswerten:
Code: Alles auswählen
var
p: Pointer = nil;
begin
ReturnNilIfGrowHeapFails := True;
p := GetMem(500 * 1024 * 1024);
if Assigned(p) then begin
WriteLn('Ok');
// (...)
end else
WriteLn('Nicht genug Speicher.');
end.
Michael
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Die Access Violation hat nichts mit der Speicherreservierung zu tun. Du solltest prüfen, ob du den Speicher erhalten hast. Wenn ja, ist definitiv genug Speicher da um die Datei zu laden (ACHTUNG: Datei mit Write-Lock vor getmem() öffnen!). Falls nicht, darfst du gar nicht erst mit dem Laden der Datei beginnen.br_klaus hat geschrieben:Ich will einem Pointer einen großen Speicherbereich zuordnen mit getmem (etwa 500 MB, nämlich eine ganze Datei laden). Aber wenn der Speicher schon zu voll ist, dann gibt es da Access Violation. Wie läßt sich so etwas abfangen?
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- m.fuchs
- Lazarusforum e. V.
- Beiträge: 2822
- Registriert: Fr 22. Sep 2006, 19:32
- OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
- CPU-Target: x86, x64, arm
- Wohnort: Berlin
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Ahh, zu schnell gelesen. Ist es wirklich eine Access Violation oder ein RunError(204)? Nur letzterer würde auf den ungenügenden Speicher hinweisen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Bei Getmem() ist das RunError(203).m.fuchs hat geschrieben:Ahh, zu schnell gelesen. Ist es wirklich eine Access Violation oder ein RunError(204)? Nur letzterer würde auf den ungenügenden Speicher hinweisen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- m.fuchs
- Lazarusforum e. V.
- Beiträge: 2822
- Registriert: Fr 22. Sep 2006, 19:32
- OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
- CPU-Target: x86, x64, arm
- Wohnort: Berlin
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Hm, ich gebe zu ich bin kein Experte für diesen Bereich.
Aber was ist dann hier passiert:

Setze ich ReturnNilIfGrowHeapFails auf True funktioniert es und ich bekomme p gefüllt mit nil zurück.
Aber was ist dann hier passiert:

Setze ich ReturnNilIfGrowHeapFails auf True funktioniert es und ich bekomme p gefüllt mit nil zurück.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Die Dokumentation zu den Run-Errors habe ich doch verlinkt. Da steht:
"204 Invalid pointer operation
This you will get if you call Dispose or Freemem with an invalid pointer (notably, Nil)"
Das heißt: du kannst in einer 32-Bit Anwendung keine 2^32 Byte anfordern.
"204 Invalid pointer operation
This you will get if you call Dispose or Freemem with an invalid pointer (notably, Nil)"
Das heißt: du kannst in einer 32-Bit Anwendung keine 2^32 Byte anfordern.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- m.fuchs
- Lazarusforum e. V.
- Beiträge: 2822
- Registriert: Fr 22. Sep 2006, 19:32
- OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
- CPU-Target: x86, x64, arm
- Wohnort: Berlin
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Der Fehler kommt aber beim Aufruf von GetMem, deswegen bin ich jetzt etwas verwirrt. Aber vielleicht verstehe ich das alles nur falsch.Socke hat geschrieben:"204 Invalid pointer operation
This you will get if you call Dispose or Freemem with an invalid pointer (notably, Nil)"
Ja, das wäre doch aber laut Doku dann ein Fall für 203:Socke hat geschrieben:Das heißt: du kannst in einer 32-Bit Anwendung keine 2^32 Byte anfordern.
[...]However, if the heap has reached the maximum size allowed by the operating system or hardware, then you will get this error.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Abfangen von Speicherüberlauf
Hallo, herzlichen Dank für die raschen Antworten. Werde es gleich mit dieser HeapVariablen ausprobieren.
Muß mich auch noch etwas korrigieren. Es sind natürlich keine 500 MB sondern "nur" 500 KB, und es wird auch keine Access Violation angezeigt, sondern es heißt da in der Fehlermeldung:
Projekt ... hat Exception-Klasse "External: SIGSEGV" ausgelöst, und dann folgt/folgen die Speicheradresse(n).
Aber da das genau dann pasierte, als ich der Zeigervariablen diese 500 K zuweisen wollte, dachte ich, muß es sich um eine Speicherverletzung handeln.
Herzlichen Dank!
Muß mich auch noch etwas korrigieren. Es sind natürlich keine 500 MB sondern "nur" 500 KB, und es wird auch keine Access Violation angezeigt, sondern es heißt da in der Fehlermeldung:
Projekt ... hat Exception-Klasse "External: SIGSEGV" ausgelöst, und dann folgt/folgen die Speicheradresse(n).
Aber da das genau dann pasierte, als ich der Zeigervariablen diese 500 K zuweisen wollte, dachte ich, muß es sich um eine Speicherverletzung handeln.
Wo kann man denn diese Dokumentation zu den Run-Errors finden? Habe überall bei den Docs nachgeschaut, bin nicht fündig geworden...Socke hat geschrieben:Die Dokumentation zu den Run-Errors habe ich doch verlinkt. Da steht:
"204 Invalid pointer operation
This you will get if you call Dispose or Freemem with an invalid pointer (notably, Nil)"
Herzlichen Dank!
Re: Abfangen von Speicherüberlauf
Siehe verstecktem Link von Socke:br_klaus hat geschrieben:Wo kann man denn diese Dokumentation zu den Run-Errors finden? Habe überall bei den Docs nachgeschaut, bin nicht fündig geworden...
Falls es noch jemanden interessiert? Der Runerror 204 scheint ein Grenzfall (bei Annäherung an maximale 32Bit-Größe) zu sein, nimmt man 100000Byte weniger, wird, so wie es sein soll, Runerror 203 ausgelöst.Socke hat geschrieben:Bei Getmem() ist das RunError(203).
Code: Alles auswählen
procedure TForm1.Button1Click(Sender: TObject);
var
p: Pointer = nil;
begin
// ReturnNilIfGrowHeapFails := True;
p := GetMem(4294967295); //Runerror (204)
p := GetMem(4294867295); //Runerror (203)
if Assigned(p) then Caption:='Ok'
else Caption:='Nicht genug Speicher.';
end;
Code: Alles auswählen
type
TLiveSelection = (lsMoney, lsChilds, lsTime);
TLive = Array[0..1] of TLiveSelection;
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Abfangen von Speicherüberlauf
Noch eine Frage zu den RuntimeErrors. Bei manchen gibt es doch die Möglchkeit, diese abzufangen durch bestimmte Kompilerschalter, zB bei Dateioperationen {$I-} Datei-Operation {$I+} und dann Abfrage einer bestimmten IO-result Variablen. Gibt es so etwas auch für andere Runtime Errors?
Herzlichen Dank.
Herzlichen Dank.
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Abfangen von Speicherüberlauf
Das ist beides das gleiche. Unter Windows wird das "Access Violation" genannt; unter Unix wird dem Prozess das Signal "Segmentation Fault" gesendet.br_klaus hat geschrieben:Muß mich auch noch etwas korrigieren. Es sind natürlich keine 500 MB sondern "nur" 500 KB, und es wird auch keine Access Violation angezeigt, sondern es heißt da in der Fehlermeldung:
Projekt ... hat Exception-Klasse "External: SIGSEGV" ausgelöst, und dann folgt/folgen die Speicheradresse(n).
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein