[gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Antworten
Linkat
Lazarusforum e. V.
Beiträge: 530
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 21.3; Lazarus 3.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 32
Wohnort: nr Stuttgart

[gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Linkat »

Hallo,
habe folgendes Problem:
Ein Maschinen-PC (mit WinNT OS) schreibt (quasi-) kontinuierlich Log-Daten auf die Festplatte (ca. 3MB pro Tag). Jetzt möchte ich möglichst Zeit nah mit einem Lazarusprogramm die aktuellen Daten (letzte 1 – 15 Sekunden) nach einem Schlüsselwort durchsuchen, um ein Ereignis auszulösen. Hierzu lade ich den gesamten Log-File in eine StringListe. In dem Timer-Event des Testprogramms:

Code: Alles auswählen

procedure TForm1.Timer1Timer(Sender:TObject);
var i,zl            :integer;
    sl              :TStringList;
begin
  Screen.Cursor:=crHourGlass;
  inc(zaehler);
  Label1.Caption:=IntToStr(zaehler);
  ListBox1.Clear;
  sl:=TStringList.Create;
  try
    sl.LoadFromFile(fname);     {fname = Filename}
    zl:=sl.Count-1;         {tail =20}
    if zl>tail then for i:=zl downto zl-tail do ListBox1.Items.Add(sl.Strings[i])
               else for i:=zl downto 0 do ListBox1.Items.Add(sl.Strings[i]);
  finally
    sl.Free;
  end;
  Screen.Cursor:=crDefault;
end;


werden die letzten (tail=20) Zeilen des Log-Files in eine Listbox/StringList übertragen. Hier kann dann nach dem Schlüsselwort gesucht werden. Wird das Timer.Interval zu klein gewählt, dann gibt es eine Zugriffsverletzung auf den Log-File (siehe Fehlermeldung)

Nun dachte ich, die Zugriffsverletzung könnte ich durch den try-finally-end Block abfangen. Leider ohne Erfolg.

Wer hat eine Idee, um die Zugriffsverletzung zu vermeiden?


Geruß, Linkat
Dateianhänge
Fehler.png
Fehler.png (10.79 KiB) 2129 mal betrachtet
Zuletzt geändert von Linkat am Mi 9. Feb 2011, 14:03, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von theo »

Ich würde eher versuchen mit TFileStream zu arbeiten. Dort kannst du den Modus definieren (fmShareDenyNone statt fmShareDenyWrite) und vor allem brauchst du nicht alles in den Speicher laden, sondern nur die letzten x KB.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von af0815 »

In der IDE oder ausserhalb der IDE.

Innerhalb der IDE wird die Exception geworfen, und du kannst dann weitersteppen. Es lassen sich im Menü IDE-Einstellungen unter Debugger neue Ausnahmen eintragen, welche beim Debuggen übergangen werden.
Ausserhald der IDE sollte das Programm die try..except Blöcker normal verarbeiten ohne das Fenster zu bringen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Socke
Lazarusforum e. V.
Beiträge: 3158
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: Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Socke »

Linkat hat geschrieben:Nun dachte ich, die Zugriffsverletzung könnte ich durch den try-finally-end Block abfangen. Leider ohne Erfolg.

Try...Finally ist dazu da, um bestimmten Code auf jeden Fall auszuführen. Was du brauchst ist try...except

Code: Alles auswählen

s1 := TStringList.Create;
try
  try
    s1.LoadFromFile(fname);
  except
    on Exception do ;
  end;
  // bla blubb
finally
  s1.Free;
end;

Übrigens: das ist keine Zugriffsverletzung sondern ein Datei-Ein-/Ausgabe-Fehler. Eine Zugriffsverletzung ist, wenn du wild im Hauptspeicher herum arbeitest ohne, dass dieser deinem Programm gehört.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Linkat
Lazarusforum e. V.
Beiträge: 530
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 21.3; Lazarus 3.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 32
Wohnort: nr Stuttgart

[gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Linkat »

Vielen Dank theo, af0815 und Socke,

@theo. Mit FileStream habe ich ein wenig herumprobiert, bin dann aber (vermutlich) an der richtigen Auswahl der Buffer gescheitert.
@af0815. Ich habe die Programme sowohl aus der IDE. als auch direkt den exe-File gestartet. Kein Unterschied.
@Socke. Prima, du hast das Problem erkannt. Jetzt funktionieren die Dateizugriffe auch bei sehr kurzen Intervallen (10 msec).

Hier ist jetzt noch einmal der Code:

Code: Alles auswählen

procedure TForm1.Timer1Timer(Sender:TObject);
var i,zl            :integer;
    sl              :TStringList;
begin
  Screen.Cursor:=crHourGlass;
  inc(zaehler);
  Label1.Caption:=IntToStr(zaehler);
  ListBox1.Clear;
  sl:=TStringList.Create;
  try
    try
      sl.LoadFromFile(fname);     {fname = Filename}
      zl:=sl.Count-1;         {tail =20}
      if zl>tail then for i:=zl downto zl-tail do ListBox1.Items.Add(sl.Strings[i])
                 else for i:=zl downto 0 do ListBox1.Items.Add(sl.Strings[i]);
    except
      on Exception do exit;
    end;
  finally
    sl.Free;
  end;
  Screen.Cursor:=crDefault;
end;



Gruß, Linkat
Linux Mint 21; Lazarus 2.2.4 FPC 3.2.2; RaspiOS

Socke
Lazarusforum e. V.
Beiträge: 3158
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: [gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Socke »

Linkat hat geschrieben:Jetzt funktionieren die Dateizugriffe auch bei sehr kurzen Intervallen (10 msec).

Brauchen da nicht schon die beiden try...finally/except-Blöcke und das Einlesen der Datei länger? Wenn das so zeitkritisch ist, solltest du darüber nachdenken auf Linux umzusteigen und Named-Pipes zu verwenden. :D
Zuletzt geändert von Socke am Mi 9. Feb 2011, 18:40, insgesamt 1-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Linkat
Lazarusforum e. V.
Beiträge: 530
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 21.3; Lazarus 3.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 32
Wohnort: nr Stuttgart

Re: [gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Linkat »

Hallo Socke,
habe in meinen Testprogrammen (Daten erzeugen, Daten lesen) die Intervalle auf 10 msec gestellt. Auch nach mehrminütigen Test war kein Konflikt aufgetreten. Mit meinem eigentlichen Programm werde ich mich im 1 - 5 Sekundenbereich bewegen. Wenn das Schlüsselwort im File gefunden wird, soll ein (Teil-) Bildschirmdump weggespeichert werden. Mein Testprogramm ist soweit fertig, dass ich morgen erste Realtests auf dem Maschinen-PC fahren werde. Bin mal gespannt, was da für neue Probleme auftauchen werden.

Gruß, Linkat
Linux Mint 21; Lazarus 2.2.4 FPC 3.2.2; RaspiOS

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: [gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von MAC »

also ein timer bearbeitet das ereignis soweit ich weis (zumindest unter win) mal in min 20 ms abständen 8) egal was da steht...

naja, trotzdem müsste ein tryblock reichen-
schreib dann aber

Code: Alles auswählen

on exception do
begin
s.free;
exit;
z1 := 1/0 // xD bööse
end;

Code: Alles auswählen

Signatur := nil;

Socke
Lazarusforum e. V.
Beiträge: 3158
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: [gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Socke »

MAC hat geschrieben:naja, trotzdem müsste ein tryblock reichen

Dann muss man TObject.Free aber auch entsprechend seiner Bestimmung verwenden. Sonst gibst du den Speicher von sl nur frei, wenn irgendetwas schief läuft, er soll aber immer freigegeben werden. Aber dafür dürfte diese Variante um einiges schneller sein.

Code: Alles auswählen

sl := TStringList.Create;
try
  //datei laden
except
  // on Exception do // kann auch weggelassen werden
  sl.Free;
  sl := nil;
end;
  sl.Free;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: [gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von MAC »

stimmt- deins ist besser, ich hab das free außerhalb der exeption vergessen ...

Code: Alles auswählen

Signatur := nil;

Socke
Lazarusforum e. V.
Beiträge: 3158
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: [gelöst] Wie kann ich eine Zugriffsverletzung unterdrücken?

Beitrag von Socke »

MAC hat geschrieben:ich hab das free außerhalb der exeption vergessen ...

und die Zuweisung von nil in der exception :P
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten