[Solved] Nutzung von Interfaces

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
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:

[Solved] Nutzung von Interfaces

Beitrag von Scotty »

Ich versuche Teile meines Programms auf eine Interfacelösung umzustellen, d.h. entweder soll per TDrawGrid gezeichnet werden oder per OpenGl. Sobald ich aber das Interface zerstöre, gibt es mit Heaptrc einen Crash.

Gibt es eine Alternative zu Heaptrace, oder mache ich was grundlegend falsch?

Code: Alles auswählen

 
type
  IScrabbleInterface=interface
    procedure Free;
   ...
end;
 
  TGlScrabbleGrid=class(TGLContext,IScrabbleInterface)
      constructor Create(aOwner:TComponent);
      destructor Destroy; override; //Destroy wird korrekt aufgerfuen
    ...
  end;
 
  TDgScrabbleGrid = class(TCustomDrawGrid,IScrabbleInterface)
    constructor Create(aOwner: TComponent);override;
    destructor Destroy; override;
  ...
  end;
 //-------------
  private
   ScrabbleGrid   : IScrabbleInterface;
 
  case fmGameOptions.rg2DMode.ItemIndex of
    0 : begin
          if not (ScrabbleGrid is TGlScrabbleGrid) then
          begin
            if assigned(ScrabbleGrid) then
            begin
              ScrabbleGrid.Free;
              ScrabbleGrid:=nil; //ohne läuft es nicht stabil
            end;
            ScrabbleGrid:=TGlScrabbleGrid.Create(pn2D);
         ...
    1 :begin
          if not (ScrabbleGrid is TDgScrabbleGrid) then
          begin
            if assigned(ScrabbleGrid) then
            begin
              ScrabbleGrid.Free;
              ScrabbleGrid:=nil;
            end;
            ScrabbleGrid:=TDgScrabbleGrid.Create(pn2D);
 
        ...
  end;//case
Zuletzt geändert von Scotty am Mo 12. Aug 2013, 10:53, insgesamt 1-mal geändert.

Benutzeravatar
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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von m.fuchs »

Probier es mal mit

Code: Alles auswählen

FreeAndNil(ScrabbleGrid as TGlScrabbleGrid)
Dann kannst du dir auch das .Free im Interface sparen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von Scotty »

Hab ich schon. FreeAndNil() ist ja, wie du sagst, identisch zu TObject.Free plus TObject:=nil;
Egal, beides hat den gleichen Effekt (ich hab alles ausprobiert.)

Benutzeravatar
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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von m.fuchs »

Und du benutzte jetzt auch das Free der Klassen, nicht das des Interfaces?
Dann liegt es aber nicht am Interface.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von Scotty »

Free stimmt schon, ich debugge ins destroy der Klassen hinein.
Ich bin mir auch nicht sicher, ob ich das Interface falsch benutze oder ob Heaptrace ein Problem damit hat.

Benutzeravatar
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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von m.fuchs »

Tritt das Problem auch auf, wenn du kein Interface benutzt? Und zeig doch mal den Code von deinem Destruktor.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von Scotty »

Leider ist der Code recht umfangreich, nur die Destruktoren bringt wohl nicht so viel. Es funktioniert (halbwegs), wenn ich kein Heaptrc benutze. Mit geht es zu 100% nicht.

Code: Alles auswählen

destructor TDgScrabbleGrid.Destroy;
begin
  Clear;
  inherited Destroy;
end;
 
destructor TGlScrabbleGrid.Destroy;
begin
  glDeleteLists(FFieldMarker,1);
  glDeleteLists(FLetterField,1);
  FPiece.Free;
  FBoard.Free;
  inherited Destroy;
end;
 

Benutzeravatar
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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von m.fuchs »

  • Tritt das Problem nur im Zusammenhang mit Interfaces auf?
  • Was bedeutet "halbwegs"?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von Scotty »

m.fuchs hat geschrieben:
  • Tritt das Problem nur im Zusammenhang mit Interfaces auf?
Es tritt nur mit Heaptrc und Interface auf.
m.fuchs hat geschrieben:[*]Was bedeutet "halbwegs"?[/list]
Wenn ich sehr schnell hin und her schalte (ich habe zwei Radiobutton als Umschalter), dann kommt es zu einem Crash. Ich wollte dem Problem mit Heaptrc nachgehen und bin dabei auf diese Sache gestoßen.

Aber wenn ich diese Diskussion richtig verstehe, dann mache ich nichts prinzipielles falsch (ich benutze interface das erste Mal). Das stellt mich schon fast zufrieden ;-)

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von mse »

Unter {$interfaces COM} (die Grundeinstellung) sind interface referenzgezählt, ihre Lebensdauer und Destruktion wird vom Compiler verwaltet. Die Freigabe geschieht entweder automatisch sobald die Interface Istanzvariable aus dem scope gerät oder durch Zuweisung eines neuen Wertes. In deinem code wird destroy() vermutlich zweimal aufgerufen, einmal explizit und ein zweites mal implizit durch die Zuweisung von nil.

Code: Alles auswählen

 
             if assigned(ScrabbleGrid) then
            begin
              ScrabbleGrid.Free; //erster aufruf von destroy
              ScrabbleGrid:=nil;  //zweiter aufruf von destroy
            end;
 
Ohne heaptrace gelingt der zweite Aufruf manchmal, da der ansich bereits freigegebene Speicher noch nicht wiederverwendet wurde. Heaptrace füllt freiegebenen Speicher unverzüglich mit Müll, darum knallt's damit immer. Mit COM interfaces sollte obenstehender code komplett entfernt werden.
Falls du die Lebensdauer der Objekte selber steuern möchtest sollte besser CORBA interface verwendet werden, da FPC öfters mal Zwischenvariablen erzeugt und wieder freigibt, worüber man keine Kontrolle hat. In MSEgui werden aus diesem Grund ausschliesslich CORBA interfaces verwendet.
http://www.freepascal.org/docs-html/ref ... x87-970007
http://www.freepascal.org/docs-html/pro ... 20001.1.37

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von Scotty »

Danke für die Erklärung. Leider klappt es mit nur .Free überhaupt nicht, da knallt es schon beim Zuweisen der anderen Klasse an das Interface. Irgendwo ist also ein Fehler im Programm. Leider kann ich nicht einfach auf CORBA umstellen, da dort das typecasting nicht geht (Rotation und einige andere Funktionen gibt es halt nur für OpenGL).
Letzten Endes missfällt mir an der Interface-Lösung auch, dass ich für jede callback Funktion eine getter und setter Funktion schreiben muss. Vielleicht ändere ich doch alles in eine abstrakte Klasse.

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von mse »

Mit COM interface braucht es kein free, es ist sogar schädlich. Die Zuweisung eines neuen Wertes zu einer COM Interface Variable ruft destroy automatisch auf, falls der reference count auf null fällt. Wie bereits geschrieben, die code Blöcke

Code: Alles auswählen

 
             if assigned(ScrabbleGrid) then
            begin
              ScrabbleGrid.Free; //erster aufruf von destroy
              ScrabbleGrid:=nil;  //zweiter aufruf von destroy
            end;
 
sollten *komplett* weggelassen werden.
Warum geht bei CORBA das typecasting nicht? Das verwende ich in MSEgui auch ab und zu.

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von Scotty »

Mit der Zuweisung von nil ohne .free bekomme ich die Meldung, dass ein Objekt mit dem gleichen Namen schon existiert (wobei Destroy tatsächlich aufgerufen wird). (Ohne beides natürlich auch.) Das geht also nicht so.
Wenn ich interface auf CORBA umstelle, dann meldet der Compiler bei if (ScrabbleGrid is TGlScrabbleGrid) then (ScrabbleGrid as TGlScrabbleGrid).Rotation:=0: "Error: Class or COM interface type expected, but got "IScrabbleInterface". Mit COM funzt das typecasting.

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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von mse »

Scotty hat geschrieben:Mit der Zuweisung von nil ohne .free bekomme ich die Meldung, dass ein Objekt mit dem gleichen Namen schon existiert (wobei Destroy tatsächlich aufgerufen wird). (Ohne beides natürlich auch.) Das geht also nicht so.
Warum machst du eine Zuweisung von nil? Wie lautet die Meldung "dass ein Objekt mit dem gleichen Namen schon existiert" genau?
Wenn ich interface auf CORBA umstelle, dann meldet der Compiler bei if (ScrabbleGrid is TGlScrabbleGrid) then (ScrabbleGrid as TGlScrabbleGrid).Rotation:=0: "Error: Class or COM interface type expected, but got "IScrabbleInterface". Mit COM funzt das typecasting.

Code: Alles auswählen

 
if ScrabbleGrid is iGlScrabbleGrid then begin
 iglscrabblegrid(scrabblegrid)....
 

Benutzeravatar
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: Alternative zu Heaptrc (oder Nutzung von Interfaces)

Beitrag von m.fuchs »

Sorry für die lange Diskussion gestern, ich hätte mal fragen sollen ob du COM nutzt.

Caste mal anders:

Code: Alles auswählen

if (ScrabbleGrid is TGlScrabbleGrid) then
   TGlScrabbleGrid(ScrabbleGrid).Rotation := 0;
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten