Ich bin absolut ratlos. Ich platziere einen Frame (TContainedFrame) auf einem Formular (TMyForm). Der Frame hat eine
public var OnClickedAButton: Event<TNotifyEvent>
.
Im OnCreate-Event des Formulars füge ich eine Methode des Formulars zum Event des Frames hinzu:
Delphi-Quellcode:
procedure TMyForm.FormCreate(Sender: TObject);
begin
containedFrame.OnClickedAButton.Add(handleAButtonClick);
end;
procedure TMyForm.handleAButtonClick(Sender: TObject);
begin
Caption := 'A button in '+Sender.ClassName+' was clicked';
end;
Das Problem: Der Destruktor von TContainedFrame erzeugt eine Zugriffsverletzung mit folgendem, mysteriösen Callstack:
Code:
System.Classes.{System.Generics.Collections}TList<System.Classes.TComponent>.IndexOf(???)
System.Classes.{System.Generics.Collections}TList<System.Classes.TComponent>.Remove(???)
System.Classes.TComponent.RemoveNotification($9672)
System.Classes.TComponent.RemoveFreeNotification($7EF3A7D0)
System._IntfClear(???)
:004CE51F System::Generics::Collections::TList__1<System::Classes::TComponent *>::IndexOf(????)
Ich kann diese
AV auch manuell herbeiführen wenn ich im Destruktor von TContainedFrame einfach nur
OnClickedAButton := nil;
sage.
Ja, die Abhilfe wäre, dort stattdessen
OnClickedAButton.Clear();
zu sagen.
Aber warum ist das so? Die
AV bekomme ich nur, wenn ich FastMM4 im FullDebugMode verwende.
Noch komischer: Ist keine
VCL im Spiel, läuft
folgender Code, trotz FastMM, problemlos durch:
Delphi-Quellcode:
program Project14;
{$APPTYPE CONSOLE}
{$R *.res}
uses FastMM4, System.SysUtils, System.Classes, Spring;
type
TContainedClass =
class
public var
myEvent: Event<TNotifyEvent>;
end;
TMyClass =
class
protected var
containedInstance: TContainedClass;
protected
procedure handleEvent(Sender: TObject);
public
constructor Create();
destructor Destroy();
override;
end;
constructor TMyClass.Create;
begin
containedInstance := TContainedClass.Create();
containedInstance.myEvent.Add(handleEvent);
end;
destructor TMyClass.Destroy;
begin
containedInstance.Free();
inherited;
end;
procedure TMyClass.handleEvent(Sender: TObject);
begin
//
end;
begin
try
TMyClass.Create().Destroy();
except
on E:
Exception do
Writeln(E.ClassName, '
: ', E.
Message);
end;
end.
Ich habe absolut keinen Ansatz, warum das hier so passiert. Ja, es ist ein wilder Wust von irgendeinem speziellen Spezialproblem. Aber jede wilde Idee macht mich froh