AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Events und SpeicherLeaks bei dynamischen Buttons
Thema durchsuchen
Ansicht
Themen-Optionen

Events und SpeicherLeaks bei dynamischen Buttons

Ein Thema von Alexander I · begonnen am 14. Jul 2015 · letzter Beitrag vom 14. Jul 2015
Antwort Antwort
Alexander I

Registriert seit: 16. Mai 2014
18 Beiträge
 
Delphi XE5 Starter
 
#1

Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 10:50
Meine Fragestellung:

Es gibt eine Form1. Diese enthält drei Buttons, ShowForm2 und ShowForm3 und Close.
Es gibt eine Form2. Diese enthält zwei zur Laufzeit mittels TButtonNames erzeugt Buttons Close und ShowForm3.
Es gibt eine Form3. Diese enthält einen zur Laufzeit mittels TButtonNames erzeugten Button Close.

In der Projekt.dpr wird zum Schluss nach Speicherlöchern abgefragt, mit: ReportMemoryLeaksOnShutdown := true;

Es gibt eine Klasse TButtonNames .
Delphi-Quellcode:

type
  TButtonNames = class
  public
   procedure LinkProcedure1(linkedProcedure: TLinkedProcedure);
   function ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn;
   function ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn;
   destructor destroy; override;
  end;
implementation

var
  handlerKlickEvent: THandlerLinkedProcedure;

destructor TButtonNames.destroy;
begin
  FreeAndNil(handlerKlickEvent);
  for i := 0 to High(fbuttons) do
    FreeAndNil(fbuttons[i]);
  inherited;
end;
procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure);
begin
  handlerKlickEvent := THandlerLinkedProcedure.Create;
  handlerKlickEvent.OnKlick := linkedProcedure;
end;

function TButtonNames.ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn;
begin
  for i := 0 to anzahlButton - 1 do
  begin
    fbuttons[i] := TBitBtn.Create(form);
    fbuttons[i].OnClick := handlerKlickEvent.GetKlick;
  end;
end;
function TButtonNames.ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn;
begin
  for i := 0 to anzahlButton - 1 do
  begin
    fbuttons[i] := TBitBtn.Create(form);
    fbuttons[i].OnClick := handlerKlickEvent.GetKlick;
   end;
end;
Das Event:
Delphi-Quellcode:
  TLinkedProcedure = procedure(sender: TObject) of object;
  THandlerLinkedProcedure = class
  private
    fLinkedProcedure: TLinkedProcedure;
  public
    property OnKlick: TLinkedProcedure read fLinkedProcedure write fLinkedProcedure;
    procedure GetKlick(sender: TObject);
  end;
Form2 und Form3 erzeugen bei Aufruf die Buttons.
In Form2:
Delphi-Quellcode:
Buttons := TButtonNames.Create;
Buttons.LinkProcedure1(EmpfangeKlick);
Buttons.ButtonsForForm2(2); // oder NamesForForm3(1);
in Form3:
Delphi-Quellcode:
Buttons := TButtonNames.Create;
Buttons.LinkProcedure1(EmpfangeKlick);
Buttons.ButtonsForForm3(1);
beide haben LinkProcedure1(EmpfangeKlick);

EmpfangeKlick sind Prozeduren in Form2 und Form3:
Delphi-Quellcode:
procedure Form2.EmpfangeKlick(Sender: TObject);
begin
  if (Sender = fbuttons[0]) then
    Close;
  if (Sender = fbuttons[1]) then
    ShowForm3;
end;
Wenn jetzt in Form1 auf Button ShowForm3 geklickt wird, erscheint Form3 mit allen erzeugten Buttons, Nämlich der Button „Close“.

Form3 wird durch klick auf „Close“ geschlossen. Form1 mit Klick auf Close geschlossen – Keine SpeicherLeaks werden angezeigt.

Wenn in Form1 auf ShowForm2 geklickt wird, erscheint Form2 mit allen erzeugten Buttons. Nämlich ShowForm3 und Close.
Form2 schließen mit Close. Form1 schließen. - Keine SpeicherLeaks werden angezeigt.

Bei Klick in Form2 auf ShowForm3 wird Form3 angezeigt mit dem Close Button.
Schließen Form3 mit Close, gehts zurück zu Form2. Form2 schließen mit Close. Form1 schließen und
SpeicherLeaks werden angezeigt.


Wenn in TButtonNames eine zweite Variable
handlerKlickEvent2: THandlerLinkedProcedure; erzeugt wird, und eine zweite Prozedure
Delphi-Quellcode:
procedure TButtonNames.LinkProcedure2(EmpfangeKlick);
begin
  handlerKlickEvent2 := THandlerLinkedProcedure.Create;
  handlerKlickEvent2.OnKlick := linkedProcedure;
end;
und aufruf in Form3:
Delphi-Quellcode:
Buttons := TButtonNames.Create;

Buttons.LinkProcedure2(EmpfangeKlick);

Buttons.ButtonsForForm3(1);
Dann werden niemals SpeicherLeaks angezeigt.

Warum muß ich eine zweite Variable und eine zweite procedure in TErzeugeButtons erstellen?
Oder, was was hab ich falsch gemacht?

Danke im voraus.

Geändert von Alexander I (14. Jul 2015 um 12:11 Uhr)
  Mit Zitat antworten Zitat
CarlAshnikov

Registriert seit: 18. Feb 2011
Ort: Erfurt
108 Beiträge
 
Delphi XE5 Enterprise
 
#2

AW: Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 11:38
Hi,

wäre interessant zu wissen wo Speicherleaks angezeigt werden.

Das Problem liegt meiner Meinung nach daran, dass du nur eine Variable hast: var handlerKlickEvent: THandlerLinkedProcedure; .


Die Referenz wird bei

Delphi-Quellcode:
 procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure);
begin
  handlerKlickEvent := THandlerLinkedProcedure.Create;
  handlerKlickEvent.OnKlick := linkedProcedure;
end;
einfach überschrieben wenn du es 2 mal aufrufst und kannst du sie nicht mehr freigeben.
Sebastian
Das kann ja wohl nicht var sein!
  Mit Zitat antworten Zitat
Benutzerbild von frankyboy1974
frankyboy1974

Registriert seit: 7. Apr 2015
Ort: SH
169 Beiträge
 
Delphi XE7 Professional
 
#3

AW: Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 11:59
Hallo,

der Quellcode kommt mir etwas seltsam vor

Delphi-Quellcode:
function TButtonNames.ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn;
begin
  for i := 0 to anzahlButton - 1 do
  begin
    fbuttons[i] := TBitBtn.Create(form);
    fbuttons[i].OnClick := handlerKlickEvent.GetKlick;
end;
function TButtonNames.ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn;
begin
  for i := 0 to anzahlButton - 1 do
  begin
    fbuttons[i] := TBitBtn.Create(form);
    fbuttons[i].OnClick := handlerKlickEvent.GetKlick;
end;
Ohne es ausprobiert zu haben, fehlt hier nicht ein (zwei) End;

mfg

frank
Java ist auch eine Insel.
Ist Delphi von Oracle?
In meiner Buchstabensuppen fehlt das C++!
  Mit Zitat antworten Zitat
Alexander I

Registriert seit: 16. Mai 2014
18 Beiträge
 
Delphi XE5 Starter
 
#4

AW: Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 12:17
@CarlAshnikov

SpeicherLeaks werden beim schließen des Programms angezeigt.



Es werden zwei verschiedene Objekte von TButtonNames erzeugt. Einmal in Form2 und einmal in Form3. Jede Form hat ihre eigenen Buttons.
Die Button von Form3 sollten also die von Form2 nicht kennen.
D.h. Button von Form3 haben ihre eigene LinkProcedure1 und die von Form2 ebenfalls ihre eigene LinkProcedure1 und dazu ihre eigene handlerKlickEvent Variable.


Sonst wäre das doch so, als wenn ich zwei Objekte vom Typ TAuto erstelle und die teilen sich ein Rad.
wenn ich

Delphi-Quellcode:
implementation
var
rad1,rad2,rad3,rad4 : TRad
mache.

Oder?
  Mit Zitat antworten Zitat
CarlAshnikov

Registriert seit: 18. Feb 2011
Ort: Erfurt
108 Beiträge
 
Delphi XE5 Enterprise
 
#5

AW: Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 12:34
Doch genau das tun sie, wenn du es so definierst. Wenn etwas nur zu einem Objekt gehören soll dann muss du das als Feld des Objektes definieren:
Delphi-Quellcode:
TAuto = class
private
  fRad1,
  fRad2,
  fRad3,
  fRad4: TRad;
public
  procedure Fahren;
end;
Ist in diesem Fall aber egal weil du bei jedem Aufruf der procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure); immer wieder über deine Referenz drüberbügelst. Dass du die Variablen unterhalb von implementation definierst sorgt nur dafür, dass außerhalb der Unit keiner darauf zugreifen kann.

Kleiner Test gefällig?

Delphi-Quellcode:
 
  TTest = class
  public
    procedure Test;
  end;

  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;


implementation

var
  globalObj: TObject;

procedure TForm2.FormCreate(Sender: TObject);
var
  vT1, vT2: TTest;
begin
  vT1 := TTest.Create;
  vT2 := TTest.Create;

  vT1.Test;
  vT2.Test;
end;

{ TTest }

procedure TTest.Test;
begin
  if assigned(globalObj) then
    raise Exception.Create('Oha')
  else
    globalObj := TObject.Create;
end;
Sebastian
Das kann ja wohl nicht var sein!
  Mit Zitat antworten Zitat
Zoot

Registriert seit: 30. Jan 2006
Ort: Hessen
110 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 12:43
Meine Fragestellung:

Es gibt eine Form1. Diese enthält drei Buttons, ShowForm2 und ShowForm3 und Close.
Es gibt eine Form2. Diese enthält zwei zur Laufzeit mittels TButtonNames erzeugt Buttons Close und ShowForm3.
Es gibt eine Form3. Diese enthält einen zur Laufzeit mittels TButtonNames erzeugten Button Close.

In der Projekt.dpr wird zum Schluss nach Speicherlöchern abgefragt, mit: ReportMemoryLeaksOnShutdown := true;

Es gibt eine Klasse TButtonNames .
Wo ist denn dein fButtons deklariert?
Und wo wird die Größe des Arrays gesetzt?
Ich sehe nirgends ein SetLength?
  Mit Zitat antworten Zitat
Alexander I

Registriert seit: 16. Mai 2014
18 Beiträge
 
Delphi XE5 Starter
 
#7

AW: Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 12:46
Ah, natürlich.

Alles klar jetzt.

Der
handlerKlickEvent: THandlerLinkedProcedure; muß zu den Objekt vars.

Vielen danke für die Erleuchtung.


Gruß
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:34 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz