Stochastische Access Violation beim Schließen einer Form!

Rund um die LCL und andere Komponenten
CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Stochastische Access Violation beim Schließen einer Form!

Beitrag von CPU-Quaeler »

Hallo Leute!

Es ist mal wieder so weit, dass meine Haare auf dem Kopf ausgehen. Bevor alle weg sind, wollte ich mal bei euch um Rat fragen. Es geht mal wieder um Promathika bei verwendung der Win32-GUI.
Ich habe eine Form zum Editieren von mathematischen Funktionen, die wie folgt aufgerufen wird:

Code: Alles auswählen

Application.CreateForm(tFFuncEdit, FFuncEdit);
FFuncEdit.showmodal;
FreeAndNil(FFuncEdit);
Ich verwende auf dieser Form OnExit-Ereignisse für diverse Eingabe-Komponenten zwecks Aktualisierung der Vorschau.

Nachdem man seine Editierungen abgeschlossen hat, kann man entweder auf das "x" gehen oder aber auf "Liste Zeichnen". Im OnClose steht nichts drin. Wenn ich auf Liste Zeichnen gehe, wird das hier aufgerufen:

Code: Alles auswählen

If FuncListDB.Ergebnisse>0 then begin
    if Fmain.PM_Source_List.Checked=false then begin
      Fmain.PM_Source_Main.Checked:=false;
      Fmain.PM_Source_List.Checked:=true;
    end;
    UMain.Cur_Settings:=UMain.ListSourceSettings;
    FMain.updateGraph;
    FFuncEdit.ModalResult:=mrOK; //das da soll angeblich alles der Classe "FFuncEdit" freigeben
  end;
Alles schön und gut, doch MANCHMAL (das ist das dumme daran) gibt es nach dem optischen Schließen der FFuncEdit eine Zugriffsverletzung. Wenn ich den Debugger einschalte, führt mich das zur Application.inc, und zwar zu "procedure TApplication.DoIdleActions;". Früher hatte ich beim Aufrufen der Form einfach FFunkEdit.free; und im "OnClose" FFuncEdit:=nil; und das hatte in Windows bestens funktioniert (nachdem ich Wochenlang nach einer Lösung gesucht habe), aber nicht in Linux. Nun ist es anders herum (mit dem Quelltext, wie aktuell angegeben)...es bringt mich einfach zum Erbrechen und verdirbt mir die Lust. Kontrollvariablen bringen nichts. Promathika macht mir zur Zeit so viel Spaß, wie Auto fahren ohne Lenkrad.

Gibt es da grundsätzlich was, was man beachten muss? Liegt es an den OnExit-Ereignissen?

Danke schonmal vorab! Wer mehr Infos möchte, gerne Fragen.

P.s.: Wie kann ich denn Quellcode als Quellcode hervorheben?
Zuletzt geändert von monta am Mi 14. Okt 2009, 23:50, insgesamt 1-mal geändert.
Grund: Highlighter

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von monta »

P.s.: Wie kann ich denn Quellcode als Quellcode hervorheben?

Code: Alles auswählen

[code=laz]
[/code]
Johannes

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Euklid »

CPU-Quaeler hat geschrieben:Gibt es da grundsätzlich was, was man beachten muss? Liegt es an den OnExit-Ereignissen?
Nach mehrfacher Durchsicht komme ich zur Erkenntnis, dass der von CPU-Quäler geschilderte Bug entweder auf ein Verständnisproblem bzgl. des Umgangs mit showmodal beruht - und für diesen Fall wäre ich _jedem_ sehr dankbar, der uns das mal stichpunktartig zusammenfassen könnte (Danke im Voraus!).

Oder aber es handelt sich nicht um einen Bug in Lazarus. Dieser Verdacht kam mir eben auf, als ich von dieser Meldung laß, die sich schon SEHR ähnlich zu unserem Problem anhört:

http://www.hu.freepascal.org/lists/fpc- ... 11927.html" onclick="window.open(this.href);return false;

Angeblich wurde der Bug gefixt. Aber lest Euch die Zeilen mal durch, das ist im Grunde genau das, was wir beobachten.
Insbesondere da in beiden Schilderungen eine AV auftritt im Zusammenhang mit
a) showmodal
b) Application.Idle bzw. Application.DoIdleActios beim Schließen der Form.

Außerdem haben wir den Aufrufstack beim Auftreten des Bugs untersucht - hier meldet der Debugger nicht eine Zeile aus unseren eigenen Quelltext.

In diesem Fall hätten wir geschätzte 40 Stunden für die Suche nach einem Bug in den Sand gesetzt, den wir garnicht finden können. Ich denke mir halt: Eigentlich können wir doch garnicht so blöd sein, dass wir mit zwei Gehirnen den Bug bezüglich eines einfachen Aufrufens/Schließens einer Form nicht finden?

Was ist Eure Meinung? Weiß jemand eventuell Konkretes? Kennt jemand Alternativen bzgl. des entsprechenden Aufrufens einer Form?

Viele Grüße, Euklid

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von mse »

Kompiliert doch mal mit heaptrace (-gh), möglicherweise geschieht die Zugriffsverletzung dann eher und reproduzierbar.

Martin

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

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von theo »

Mal ne blöde Frage: Wieso erzeugt und zerstört ihr das Formular überhaupt während der Programmausführung?
Tritt ein Fehler auch auf, wenn das Formular im .lpr erzeugt wird (default) und dann nur noch mit show/hide angezeigt wird?
Ich meine nicht, dass da nicht evtl ein Bug ist, aber der Verzweiflung nach sind doch auch pragmatische Lösungen gesucht, oder?

Ohne es wirklich zu wissen, könnte ich mir auch vorstellen, dass ein mit Application.CreateForm erzeugtes Formular gar nicht vom User zerstört werden sollte. Das tut Laz ja auch nicht.

Code: Alles auswählen

begin
  {$I project1.lrs}
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
Vllt eher MyForm:=TMyForm.Create...

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Patito »

Also solche Fehler sind sehr typisch wenn man Formulare freigibt.
Das Problem hier ist vermutlich:

Application.CreateForm(tFFuncEdit, FFuncEdit);

Das teilt Application mit, dass es sich um das Formular kümmern soll. Und
wenn man das Formular einfach freigibt ohne Application davon zu informieren
geht das dann schief.

Wenn man das Formular selbst unter kontrolle halten will (erzeugen + freigeben) geht das
zumindest in Delphi so:

var MyForm: TMyForm;
begin
MyForm := TMyForm.Create(nil); // kein Owner
MyForm.ShowModal;
MyForm.Free;
end;

Es gibt dann aber noch eine ganze Menge anderer Probleme, die in Delphi zumindest auftauchen können.
Z.B. sind viele Komponenten schlecht geschrieben und vertragen es einfach nicht freigegeben zu werden.
(das macht dann die Komponente zum Beispiel für die Verwendung innerhalb einer DLL völlig unbrauchbar).

CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von CPU-Quaeler »

Danke schonmal für eure Antworten!
@theo: Promathika soll ja einige Fenster im Laufe der Zeit erhalten. Zur Zeit sind es drei. Auf diesen Fenstern können sich Tabs, Bilder und andere Ressourcenfresser aufhalten. Daher wollen wir schon nicht benötigtes auch nicht im Hintergrund ausgeblendet, sondern freigegeben haben.

@mse: Mit Heaptrc und Debugger im Hintergrund muss man die Form viel öfter öffnen und schließen, bis die AV kommt, als ohne. Aber nichts desto trotz, die Heaptrc gibt in dem Fall in Windows nur einen Haufen Addressen aus und proceduren, die nicht von mir sind.

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

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von theo »

CPU-Quaeler hat geschrieben:Danke schonmal für eure Antworten!
@theo: Promathika soll ja einige Fenster im Laufe der Zeit erhalten. Zur Zeit sind es drei. Auf diesen Fenstern können sich Tabs, Bilder und andere Ressourcenfresser aufhalten. Daher wollen wir schon nicht benötigtes auch nicht im Hintergrund ausgeblendet, sondern freigegeben haben.
Naja, da würde ich mir jetzt nicht soo den Kopf machen. Ich meine eh dir die Lust vergeht, wie du sagst.
Hast du meinen Vorschlag (von Patito bestätigt) mit
MyForm := TMyForm.Create(nil);
getestet?

Socke
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: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Socke »

Der Owner im Konstruktor dürfte mit dem Problem überhaupt nichts zu tun haben. Dieser kommt von TComponent und ermöglicht nur das automatische Freigeben von anderen Komponenten. Das heißt, wenn der Owner freigegeben wird, gibt er alle Komponenten frei, die registriert sind. Und da TApplication auch von TComponent abstammt, kann man auch TForm.Create(Application) ausführen. Wenn ein Formular zur Laufzeit erstellt und auch wieder freigegeben wird, kann man mit Owner=nil allenfalls ein wenig Overhead sparen.

Weiterhin sollte es egal sein, ob man Application.CreateForm(TForm,Formvar) oder TForm.Create(Application) aufruft. Der Unterschied könnte höchstens in der MainForm-Behandlung liegen, wo ich mir aber auch nicht sicher bin.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Patito »

@Socke:
Das ist nicht richtig. Der AV tritt ja in Application.DoIdleActions() auf.

Application.CreateForm() fügt das Formular zu Application.FFormList hinzu.
Application.DoIdleActions() macht etwas mit allen Forms, die in Application.FFormList sind.

-> AV

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Euklid »

Danke auch von mir für die zahlreichen Antworten und Tipps!
theo hat geschrieben: Hast du meinen Vorschlag (von Patito bestätigt) mit
MyForm := TMyForm.Create(nil);
getestet?
Habe gestern mit CPU-Quäler telefoniert: Der Bug tritt auch mit TForm.Create auf. Das würde die Theorie von Socke und zuletzt von Patito bestätigen.

Der Witz ist, dass es sich um einen reinen Windows-Bug handelt. Ich verwende ausschließlich Linux, habe IMMER die heaptrc eingespannt, und es kommt nie zur AV.
Wenn nichts anderes hilft, wird uns zunächst wahrscheinlich nichts anderes übrig bleiben, als Theos Vorschlag mit show und hide umzusetzen. Das Problem ist eben, dass wir auf so ziemlich jeder Form eine Preview installiert haben, die es dem Anwender ermöglicht, die Auswirkungen seiner Einstellungen direkt zu beobachten. Diese Preview frisst Speicher.

Ich werde mal versuchen, den Bug mithilfe eines ganz simplen Programms zu provozieren. Gelänge mir das, wäre es wohl tatsächlich ein Lazarus-Bug, den ich reporten könnte. Dann würde sich das Problem zumindest auf lange Sicht auflösen.

Viele Grüße, Euklid

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Patito »

@Euklid:
Ist es mit TForm.Create(nil) immer noch derselbe AV?

Application.CreateForm() ist auf jedenfall falsch wenn man das Formular selbst freigeben will.
TForm.Create(nil) sollte zumindest erst mal das Problem in DoIdleActions() lösen.

Es gibt aber wie gesagt noch einen Haufen weiterer Fehlerquellen, auf die man achten muß.

Z.B ist die Verwendung von Application.ProcessMessages() fast immer ein Fehler, da
dadurch der Programmablauf gewaltig durcheinander kommen kann.

Es kann da zu solchen Sachen kommen:
1) Ereignisbehandlung einer Komponente ruft Application.ProcessMessages auf
2) Klick auf X des Formulars mit der Komponente wird verarbeitet
3) Modales Formular schließt sich
4) Formular wird freigegeben
5) Ereignisbehandlung vom Anfang will in ihrem Code nach dem ProcessMessages weitermachen,
aber das Formular samt Komponente sind schon freigegeben worden! -> AV

Wenn z.B. Application.ProcessMessages in einer Komponente intern sinnlos verwendet wird bleibt
oft nichts anderes übrig als die Komponente komplett zu entsorgen.

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Scotty »

Der Witz ist, dass es sich um einen reinen Windows-Bug handelt
Ich habe auch beobachtet, dass Linux oft weniger sensibel auf Fehler reagiert. Andererseits ist dadurch Windows eine gute Möglichkeit, Bugs zu finden. Ich habe in meinem Programm zum Beispiel bei Close eine SIGSEV gehabt, die darauf zurückzuführen war, dass ich bei Programmbeginn an zwei Stellen in eine Ini-Datei geschrieben habe...

Socke
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: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Socke »

Scotty hat geschrieben:
Der Witz ist, dass es sich um einen reinen Windows-Bug handelt
Ich habe auch beobachtet, dass Linux oft weniger sensibel auf Fehler reagiert. Andererseits ist dadurch Windows eine gute Möglichkeit, Bugs zu finden. Ich habe in meinem Programm zum Beispiel bei Close eine SIGSEV gehabt, die darauf zurückzuführen war, dass ich bei Programmbeginn an zwei Stellen in eine Ini-Datei geschrieben habe...
Wo viele Fehler sind, kann man auch viele Fehler finden :twisted:
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Stochastische Access Violation beim Schließen einer Form!

Beitrag von Euklid »

Hallo zusammen,

soeben ist bei mir der selbe Bug das erste Mal in Linux aufgetreten: Eine AV in DoIdleActions. Genauer, hier:

Code: Alles auswählen

procedure TApplication.DoIdleActions;
var
  i: Integer;
  CurForm: TCustomForm;
  AForm: TForm;
begin
  for i := 0 to Screen.CustomFormCount - 1 do begin
    CurForm:=Screen.CustomForms[I];
    if CurForm.HandleAllocated and CurForm.Visible and CurForm.Enabled then
      CurForm.UpdateActions;
  end;
  if FFormList<>nil then begin
    for i:=0 to FFormList.Count-1 do begin
      AForm:=TForm(FFormList[i]);
      if AForm.FormStyle=fsSplash then   // <------- HIER: Segment Violation
        AForm.Hide;
    end;
  end;
end;
Allerdings ist dies bei einer anderen Form (FEinstellungen) passiert, die aber auf die selbe Weise von uns erstellt bzw. freigegeben wird.

Der Aufrufstack ist wenig aussagekräftig:

Code: Alles auswählen

#0 DOIDLEACTIONS(0x7f510cade380) at include/application.inc:917
#1 IDLE(true, 0x7f510cade380) at include/application.inc:334
#2 HANDLEMESSAGE(0x7f510cade380) at include/application.inc:1136
#3 RUNLOOP(0x7f510cade380) at include/application.inc:1269
#4 APPRUN({Proc = {procedure (^pointer)} 0x7fff14b4e310, Self = 0x7f510cade380}, 0x7f510c984090) at include/interfacebase.inc:49
#5 RUN(0x7f510cade380) at include/application.inc:1257
#6 main at Promathika.lpr:18
Nehme an, das sagt Euch genauso wenig wie mir?
Zuletzt geändert von Euklid am Sa 17. Okt 2009, 10:03, insgesamt 1-mal geändert.

Antworten