Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Räumt diese Komponente hinter sich auf? (https://www.delphipraxis.net/197385-raeumt-diese-komponente-hinter-sich-auf.html)

hzzm 3. Aug 2018 05:06

Delphi-Version: 10 Seattle

Räumt diese Komponente hinter sich auf?
 
Guten Morgen,

räumt diese Komponente hinter sich auf (sind die Destruktoren korrekt)?

Delphi-Quellcode:
unit ImageMultiStates;

    interface

    uses
      Vcl.Graphics, Vcl.StdCtrls, System.SysUtils, System.Classes, Vcl.Controls, Vcl.ExtCtrls, Forms, Generics.Collections;

    type

      TPic = class(TCollectionItem)
      private
        FPicture: TPicture;
        procedure SetPicture(const value: TPicture);
      protected
        function GetDisplayName: String; override;
      public
        procedure Assign(Source: TPersistent); override;
        constructor Create(Collection: TCollection); override;
      published
        property Picture: TPicture read FPicture write SetPicture;
      end;

      TPictures = class(TOwnedCollection)
      private
        function GetPic(Index: Integer): TPic;
        procedure SetPic(Index: Integer; Value: TPic);
      public
        constructor Create(AOwner: TComponent);
        destructor Destroy;
        property Picture[Index: Integer]: TPic read GetPic write SetPic;
      end;

      TImageMultiStates = class(TImage)
      private
        FPictures: TPictures;
        FOnMouseDownPic: Integer;
        FOnMouseUpPic: Integer;
        procedure SetPictures(const Value: TPictures);
      public
        ActivePic: Integer;
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure ActivatePic(Index: Integer);
        procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
        procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
      published
        property Pictures: TPictures read FPictures write SetPictures;
        property OnMouseDownPic: Integer read FOnMouseDownPic write FOnMouseDownPic;
        property OnMouseUpPic: Integer read FOnMouseUpPic write FOnMouseUpPic;
      end;

    procedure Register;

    implementation

    constructor TPic.Create(Collection: TCollection);
    begin
      inherited;
      FPicture := TPicture.Create;
    end;

    procedure TPic.Assign(Source: TPersistent);
    begin
      if Source is TPic then
        FPicture := TPic(Source).FPicture
      else
        inherited;
    end;

    procedure TPic.SetPicture(const Value: TPicture);
    begin
      FPicture.Assign(Value);
      if Index=0 then
        TImageMultiStates(TPictures(GetOwner).GetOwner).Picture.Assign(Value);
    end;

    function TPic.GetDisplayName;
    begin
      Result := Format('Picture %d',[Index]);
    end;


    constructor TPictures.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner, TPic);
    end;

    destructor TPictures.Destroy;
    begin
      inherited Destroy;
    end;

    procedure TPictures.SetPic(Index: Integer; Value: TPic);
    begin
      inherited SetItem(Index, Value);
    end;

    function TPictures.GetPic(Index: Integer): TPic;
    begin
      Result := inherited GetItem(Index) as TPic;
    end;


    constructor TImageMultiStates.Create(AOwner: TComponent);
    begin
      inherited;
      FOnMouseDownPic := -1;
      FOnMouseUpPic := -1;
      FPictures := TPictures.Create(AOwner);
    end;

    destructor TImageMultiStates.Destroy;
    begin
      FPictures.Free;
      inherited;
    end;

    procedure TImageMultiStates.SetPictures(const Value: TPictures);
    begin
      FPictures.Assign(Value);
    end;

    procedure TImageMultiStates.ActivatePic(Index: Integer);
    begin
      if (Index < FPictures.Count) and (Index >= 0) then
      begin
        ActivePic := Index;
        Picture.Assign(TPic(FPictures.Items[Index]).FPicture);
      end
      else
      begin
        ActivePic := -1;
        Picture.Assign(nil);
      end;
    end;

    procedure TImageMultiStates.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if FOnMouseDownPic<>-1 then
        Picture.Assign(TPic(FPictures.Items[FOnMouseDownPic]).FPicture);
      inherited;
    end;

    procedure TImageMultiStates.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if FOnMouseUpPic<>-1 then
        Picture.Assign(TPic(FPictures.Items[FOnMouseUpPic]).FPicture);
      inherited;
    end;

    procedure Register;
    begin
      RegisterComponents('Standard', [TImageMultiStates]);
    end;

    end.

Daniel 3. Aug 2018 05:16

AW: Räumt diese Komponente hinter sich auf?
 
Ein wichtiges Werkzeug in solchen Fragen: Delphi kann Dir das selbst sagen.
Wenn Du im Projektquellcode die Anweisung „ReportMemoryLeaksOnShutdown:=true;“ setzt, bekommst Du einen Hinweis, wenn am Ende etwas nicht artig aufgeräumt wird.
Die dahinterstehende Buchhaltung kostet Rechenzeit, o.g. Anweisung sollte also nur zum Testen in Deinem Projekt stehen.

Der schöne Günther 3. Aug 2018 05:32

AW: Räumt diese Komponente hinter sich auf?
 
Und dann spiele doch mal etwas mit deiner eigenen Komponente wenn
Delphi-Quellcode:
ReportMemoryLeaksOnShutdown = true
ist. Oder noch besser: Schreibe vernünftige Unit-Tests. Zum Beispiel für
Delphi-Quellcode:
TPic.Assign(..)
. Da wirst du zum Beispiel feststellen dass das was du im Konstruktor in FPicture reingesteckt hast niemals freigegeben wird.


PS: "Richtig aufräumen" beinhaltet mehr als nur Speicher der Delphi-Objekte freigeben. Wenn deine Klasse beispielsweise mit Dateien hantiert und ein Handle nicht mehr freigibt, eine Netzwerkverbindung nicht schließt, … All sowas.

jaenicke 3. Aug 2018 09:19

AW: Räumt diese Komponente hinter sich auf?
 
So wie du es aktuell hast, ist die korrekte Speicherverwaltung sehr schwer. Denn im Assign kopierst du z.B. nur den Pointer auf ein fremdes Objekt. Dadurch darf dieses Objekt außen gar nicht freigegeben werden, aber auch das Objekt, das den Pointer bekommen hat, kann es nicht tun, da es ja nicht weiß was außen mit dem Objekt passiert.

Delphi selbst macht das so (in TPicture z.B.), dass schlicht im Setter und in Assign der Inhalt kopiert wird. Dadurch sind die einzelnen Objekte voneinander unabhängig und können im Destruktor alles problemlos freigeben, das sie selbst erzeugt haben.

Pfaffe 3. Aug 2018 16:57

AW: Räumt diese Komponente hinter sich auf?
 
In meinen Projektdateien steht immer:
{$IFDEF DEBUG}
ReportMemoryLeaksOnShutdown:= True;
{$ENDIF}

MicMic 4. Aug 2018 06:34

AW: Räumt diese Komponente hinter sich auf?
 
Wie ist es denn eigentlich zu bewerten bzw. was passiert, wenn hier und da ein Speicher nicht freigegeben wird? Es wird dann ja wohl meistens um kleine Sachen gehen.
Ein Betriebssystem wird doch damit bestimmt auch umgehen können. Ich könnte mir vorstellen, dann ist halt irgendwo noch was im Speicher und Windows ist's schnuppe. Schaut natürlich bestimmt wieder anders aus, wenn der Rechner 24h an ist.

Michael

haentschman 4. Aug 2018 06:39

AW: Räumt diese Komponente hinter sich auf?
 
Moin...:P
Wenn der Prozess (Anwendung) beendet wird, dann räumt Windows den gesamten Speicher des Prozesses auf. Aber es soll auch Anwendungen geben die 365/24 laufen...:zwinker: Für die wäre es fatal wenn irgend eine procedure nicht aufräumt sondern den Speicher zumüllt. 8-)

KodeZwerg 4. Aug 2018 07:55

AW: Räumt diese Komponente hinter sich auf?
 
Windows stehen auch nur eine bestimmte Anzahl an Handles zur Verfügung, also kann es da irgendwann auch knapp werden.

freimatz 6. Aug 2018 15:33

AW: Räumt diese Komponente hinter sich auf?
 
Zitat:

Zitat von haentschman (Beitrag 1409744)
Aber es soll auch Anwendungen geben die 365/24 laufen...:zwinker:

Kann gar nicht mehr sein. Irgendwann kommt Windows 10 und macht selbständig einen Neustart :twisted:

Der schöne Günther 7. Aug 2018 09:12

AW: Räumt diese Komponente hinter sich auf?
 
Wenn du Windows für Heimversionen einsetzt, dann ja.
Es ist eher dass die Anlagen das können sollten, früher oder später fällt beim Kunden eh der Strom aus ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:44 Uhr.
Seite 1 von 2  1 2      

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