ActiveX and HeapTrace

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

ActiveX and HeapTrace

Beitrag von theo »

Ich habe gestern hier eine Frage gestellt: http://lists.freepascal.org/lists/fpc-d ... 30356.html
Leider habe ich keine Antwort bekommen.

Problem: Ich habe ein ActiveX Control "TAxcSpVoice" das nur bei eingeschaltetem Heaptrace beim "freen" crasht.

Gibt es hier jemand, der genug Einblick in die Materie hat, um eine Vermutung abzugeben, wieso das passiert?
Deutet es auf ein tiefer liegendes Problem hin, oder ist es ohne Heaptrace bedenkenlos?

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: ActiveX and HeapTrace

Beitrag von mse »

Deine Mail wurde vermutlich vom Listserver unterschlagen, Ich habe sie jedenfalls nicht bekommen.
Beim Mischen von referenzgezählten COM interfaces (ich denke, bei ActiveX sind immer irgenwo COM-Interfaces im Spiel) und TObject/TComponent.Free gibt es fast immer Probleme. Free() darf erst dann aufgerufen werden, wenn alle interface Referenzen _Release() aufgerufen haben und der Referenzzähler 0 erreicht hat. Mit TComponent kann man das nicht wissen, da Tcomponent _Addref() und _Release() ignoriert. Bei FPC kommt dazu, dass FPC immer mal wieder lokale interface Variablen erzeugt und wieder freigibt, welche nicht unter der Kontrolle der Programmierer stehen. Aber auch mit Delphi ist die Sache nicht wasserdicht. Wovon stammt TAxcSpVoice ab?

Martin

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: ActiveX and HeapTrace

Beitrag von m.fuchs »

Angekommen ist die Mail, aber ich weiß nicht ob die Mailingliste glücklich gewählt war. Statt FPC-Devel hätte ich eher FPC-Pascal genommen.

Was passiert denn wenn du auf das .Free verzichtest? Meldet HeapTrace dann ein Speicherleck? Kann es einfach sein, dass dein Objekt automatisch zerstört wird, wenn keine Referenz mehr daufliegt (Stichwort: COM-Interface)?

Möglicherweise hält HeapTrace ja irgendeine Referenz auf alle Objekte, was dann den Fehler erzeugt.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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

Re: ActiveX and HeapTrace

Beitrag von theo »

Danke für die Antwort
mse hat geschrieben: Wovon stammt TAxcSpVoice ab?
TAxcSpVoice = Class(TActiveXContainer)

TActiveXContainer = class(TWinControl, IUnknown, IOleClientSite,
IOleControlSite, IOleInPlaceSite, IOleInPlaceFrame, IDispatch)

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

Re: ActiveX and HeapTrace

Beitrag von theo »

m.fuchs hat geschrieben:
Was passiert denn wenn du auf das .Free verzichtest? Meldet HeapTrace dann ein Speicherleck?
Ja, tut es. Darum kann ich Heaptrace so eigentlich nicht verwenden, weil es entweder crasht oder Leaks anzeigt, die wahrscheinlich nicht unter meiner Kontrolle sind.
Zuletzt geändert von theo am Do 29. Nov 2012, 15:33, insgesamt 1-mal geändert.

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

Re: ActiveX and HeapTrace

Beitrag von theo »

Hier noch der automatisch generierte Code, falls es jemanden interessiert.

http://www.theo.ch/lazarus/SpeechLib_5_4_TLB.zip

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: ActiveX and HeapTrace

Beitrag von mse »

theo hat geschrieben:
TAxcSpVoice = Class(TActiveXContainer)

TActiveXContainer = class(TWinControl, IUnknown, IOleClientSite,
IOleControlSite, IOleInPlaceSite, IOleInPlaceFrame, IDispatch)
TWincontrol stammt von TComponent ab welches _Addref() und _Release() folgendermassen -das heisst gar nicht- implementiert:

Code: Alles auswählen

 
function TComponent._AddRef: Integer;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
begin
  if Assigned(VCLComObject) then
    Result := IVCLComObject(VCLComObject)._AddRef
  else
    Result := -1;
end;
 
function TComponent._Release: Integer;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
begin
  if Assigned(VCLComObject) then
    Result := IVCLComObject(VCLComObject)._Release
  else
    Result := -1;
end;
 
 
Nun wird's schwierig. ;-)
Setzt TActiveXContainer VCLComObject?

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

Re: ActiveX and HeapTrace

Beitrag von theo »

mse hat geschrieben: Nun wird's schwierig. ;-)
Setzt TActiveXContainer VCLComObject?
Weiss nicht, da kenne ich mich zu wenig aus.
Der Code ist hier einsehbar:
http://svn.freepascal.org/cgi-bin/viewv ... ot=lazarus

Danke.

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: ActiveX and HeapTrace

Beitrag von mse »

In activexcontainer.pas direkt nicht. Könntest du mal schauen, ob ein Vorfahre in Lazarus das tut?
Falls VCLComObject nirgendwo gesetzt wird (könntest du mit dem Debugger überprüfen) ist die Situation so, dass die COM Referenzzählung ausser Betrieb ist und TAxcSpVoice mit Destroy() freigegeben werden muss. Wie schon erwähnt darf das erst dann geschehen, wenn nirgendwo mehr eine interface Referenz auf das Objekt gehalten wird.
Falls die Referenzzählung in Betrieb ist, darf TAxcSpVoice.Free() nicht aufgerufen werden und der Speicher sollte automatisch freigegeben werden. Falls nicht ist das typisch für COM interface und bedingt dann mühsame Suche nach der Ursache...

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

Re: ActiveX and HeapTrace

Beitrag von theo »

Danke ich schau am Abend mal nach.

Was hältst du von dieser Eigenschaft des ActiveXContainer:

201 {When set, binds ActiveX component to control.
202 When cleared, detaches the component from the control
203 If Classname is provided the ActiveX component will also be created and destroyed
204 automatically.}
205 property Active:boolean read FActive write SetActive;

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: ActiveX and HeapTrace

Beitrag von mse »

theo hat geschrieben: Was hältst du von dieser Eigenschaft des ActiveXContainer:
Aua. Damit habe ich mich zum Glück noch nie herumschlagen müssen.

Martin

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

Re: ActiveX and HeapTrace

Beitrag von theo »

mse hat geschrieben:In activexcontainer.pas direkt nicht. Könntest du mal schauen, ob ein Vorfahre in Lazarus das tut?
Im ganzen Lazarus Source Tree kommt dieses Property nicht vor (Find in Files).
Nur in der FPC RTL, aber die kennst du ja.

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: ActiveX and HeapTrace

Beitrag von mse »

Dann können wir wohl davon ausgehen, dass die Instanz nicht durch die COM Referenzzählung freigegeben wird, es sei denn irgendein anderes Begleitobjekt erfüllt diese Aufgabe. Ich würde mal den Konstrukteur der Komponente (Ludo Brands) fragen, wie er sich die Sache vorgestellt hat.

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

Re: ActiveX and HeapTrace

Beitrag von theo »

mse hat geschrieben: Ich würde mal den Konstrukteur der Komponente (Ludo Brands) fragen, wie er sich die Sache vorgestellt hat.
Naja, es funktioniert alles prima und es gibt im Normalbetrieb auch kein SIGSEGV, ausser beim "freen" mit eingeschaltenem HeapTrace.
Deshalb weiss ich gar nicht so richtig, ob das ein Bug ist, und wenn ja, ob da nicht evtl. HeapTrace falsch gewickelt ist.

Das herauszufinden war eigentlich der Grund für meine Frage. Je nachdem werde ich einen Bugtracker Eintrag machen.

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: ActiveX and HeapTrace

Beitrag von mse »

Was hier möglicherweise passiert, ist, dass du die Instanz freigibst und später _Release() oder eine andere interface Methode aufgerufen wird. Solange der Speicher nicht wiederverwendet wird, merkt man nichts davon. Heaptrace füllt freigegebenen Speicher mit Müll (0f0f0f0f) damit der Fehler sofort auftritt und nicht erst beim Kunden. ;-)

Martin.

Antworten