Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Warum zerstören sich meine Classen (https://www.delphipraxis.net/159283-warum-zerstoeren-sich-meine-classen.html)

EWeiss 21. Mär 2011 22:54

Warum zerstören sich meine Classen
 
Ich bekomme langsam die Krise.
Ich hab ein neues Control angefangen uGrid..

Delphi-Quellcode:
type
  ISkinGrid = interface
    ['{89A97429-5E4B-43B6-87D8-381DD4E8CF21}']
    function GetHandle: hWnd;
    property Handle: hWnd read GetHandle;
  end;

  TSkinGrid = class(TInterfacedObject, ISkinGrid)
  private
    FHGrid: HWND;
    FWidth: Integer;
    FHeight: Integer;
    Img:    cardinal;
    dwStyle: DWORD;
    IsInitialized: BOOL;
    FOffsetX: Integer;
    FOffsetY: Integer;
    function GetOffsetY: Integer;
    function GetOffsetX: Integer;
    function GetHandle: hWnd;
    procedure DrawGrid(WinHandle: HWND);
  public
    property Handle: HWND Read FhGrid;
    property Width: Integer Read FWidth;
    property Height: Integer Read FHeight;
    property OffsetX: Integer read GetOffsetX write FOffsetX;
    property OffsetY: Integer read GetOffsetY write FOffsetY;
    constructor Create(hOwner: HWND; FullpathImageName: string;
       x, y, xW, yH, OffsX, OffsY, ButID: Integer);
    destructor Destroy; override;
  end;
sollte alles in Ordnung sein.

Classe wird ordnungsgemäß erstellt.
Danach stimmen alles meine Variablen.

Mit einmal zerstört sie sich selbst und alles ist weg.
Warum?

Der Aufruf wie zuvor.

Delphi-Quellcode:
    BoxGrid := CTRL_GridCreate(hMain, SKAERO_FOLDER +
      'Grid.png', 150, 67, 585, 257, 20, 10, ID_BOXGRID);
    SKAERO_SetAnchorMode(BoxGrid.Handle, ANCHOR_HEIGHT_WIDTH);
    SKAERO_SetZorder(BoxGrid.Handle, HWND_TOP);

Siehe Bilder..
Wie man sehen kann sind bei DrawGrid alle Eigenschaften gelöscht.

gruss

rollstuhlfahrer 21. Mär 2011 23:05

AW: Warum zerstören sich meine Classen
 
Interfaces lösen sich selbst auf, sobald nicht mehr auf sie zugegriffen wird (Referenz-Zähler = 0). Hast du eventuell eine gleichnamige lokale Variable zu deiner eventuell vorhandenen globalen Variable?

Bernhard

Namenloser 21. Mär 2011 23:08

AW: Warum zerstören sich meine Classen
 
Du musst bei Interfaces die Referenzzählung beachten. Wenn der Referenzzähler 0 erreicht, wird das Objekt automatisch zerstört.
Das kann z.B. passieren, wenn du Klassen- und Interface-Variablen mischt:
Delphi-Quellcode:
type
  IMyObj = interface
    …
  end;

  TMyObj = class(TInterfacedObject, IMyObj)
    …
  end;

var
  obj: TMyObj;
  intf: IMyObj;
begin
  obj := TMyObj.Create; // Referenzzähler von obj ist 0
  intf := obj; // Referenzzähler von obj wird inkrementiert → 1
  intf := nil; // Referenzzähler von obj wird dekrementiert → 0 → obj wird freigegeben
  { ab hier kannst du obj nicht mehr benutzen }
end
Dabei muss nicht unbedingt eine Interface-Variable auf nil gesetzt werden, es kann auch sein, dass in einer Subroutine ein Objekt einer lokalen Interface-Variable zugewiesen wird. Am Ende der Subroutine wird die Variable nämlich finalisiert, der Referenzzähler wird also ebenfalls dekrementiert, natürlich mit dem selben Effekt.

Deshalb sollte man Interfaces wenn dann immer konsequent verwenden.

EWeiss 21. Mär 2011 23:34

AW: Warum zerstören sich meine Classen
 
Hier ist mal meine komplette Klasse..
Hab nicht gedacht das es so schwierig mit den Interfacen ist.

Delphi-Quellcode:
unit uGrid;

interface

uses Windows, Classes, Messages, SysUtils, uGlobal, uGDIUnit, uSkin, uTrackBar;

type
  ISkinGrid = interface
    ['{89A97429-5E4B-43B6-87D8-381DD4E8CF21}']
    function GetHandle: hWnd;
    property Handle: hWnd read GetHandle;
  end;

  TSkinGrid = class(TInterfacedObject, ISkinGrid)
  private
    FHGrid: HWND;
    FWidth: Integer;
    FHeight: Integer;
    Img:    cardinal;
    dwStyle: DWORD;
    IsInitialized: BOOL;
    FOffsetX: Integer;
    FOffsetY: Integer;
    function GetOffsetY: Integer;
    function GetOffsetX: Integer;
    function GetHandle: hWnd;
    procedure DrawGrid(WinHandle: HWND);
  public
    property Handle: HWND Read FhGrid;
    property Width: Integer Read FWidth;
    property Height: Integer Read FHeight;
    property OffsetX: Integer read GetOffsetX write FOffsetX;
    property OffsetY: Integer read GetOffsetY write FOffsetY;
    constructor Create(hOwner: HWND; FullpathImageName: string;
       x, y, xW, yH, OffsX, OffsY, ButID: Integer);
    destructor Destroy; override;
  end;

function GridProc(WinHandle: HWND; Msg: UINT; wP: WParam; lP: LParam): LRESULT; stdcall;

var
 SkinGrid : TSkinGrid;

implementation

constructor TSkinGrid.Create(hOwner: HWND; FullpathImageName: string;
  x, y, xW, yH, OffsX, OffsY, ButID: integer);

var
  wc:    TWndClassEx;
  zClass: PAnsiChar;

begin
  inherited Create;

  with SkinEngine do
  begin
    zClass   := SKGRID;
    wc.cbSize := SIZEOF(wc);
    IsInitialized := GetClassInfoEx(skInstance, zClass, wc);
    if IsInitialized = False then
    begin
      wc.cbSize    := SIZEOF(wc);
      wc.style     := CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS;{ or CS_PARENTDC;}
      wc.lpfnWndProc := @GridProc;
      wc.cbClsExtra := 0;
      wc.cbWndExtra := EXTEND_EXTRA * 4;
      wc.hInstance := skInstance;
      wc.hIcon     := 0;
      wc.hCursor   := 0;
      wc.hbrBackground := 0;
      wc.lpszMenuName := nil;
      wc.lpszClassName := zClass;
      wc.hIconSm   := wc.hIcon;
      if RegisterClassEx(wc) <> 0 then
        IsInitialized := True;
    end;

    if IsInitialized = True then
    begin
      dwStyle := WS_CHILD or WS_VISIBLE or WS_TABSTOP;
      // Erstelle das GDIPLUS image von Datei
      Img := AddResource(PAnsiChar(FullpathImageName));
      if Img <> 0 then
      begin
        // Hole die Thumb GDIPLUS image größe
        GetImageSize(Img, imgW, imgH);

        FWidth  := xW;
        FHeight := yH;
        FOffsetX := OffsX;
        FOffsetY := OffsY;

        FHGrid := CreateWindowEx(WS_EX_TRANSPARENT,
          SKGRID, nil, dwStyle, x, y, xW, yH,
          hOwner, ButID, skInstance, nil);

        if FHGrid <> 0 then
        begin
          // Speichere das Image Handle in die Property
          SetImageProperty(FHGrid, PROP_STYLE, BS_GROUPBOX);
          SetImageProperty(FHGrid, GRID_IMAGE, Img);

          SkinGrid := @FHGrid;
          SkinGrid.Img := Img;
          SkinGrid.dwStyle := dwStyle;
          SkinGrid.FWidth := xW;
          SkinGrid.FHeight := yH;
          SkinGrid.FOffsetX := OffsX;
          SkinGrid.FOffsetY := OffsY;

        end else
          // Image löschen wenn Fehler
          DeleteResource(Img);
      end;
    end;
  end;
end;

function GridProc(WinHandle: HWND; Msg: UINT; wP: WParam; lP: LParam): LRESULT;
var
  ps: TPaintstruct;

begin

  with SkinEngine do
  begin
    case Msg of
      WM_ERASEBKGND:
      begin
        Result := 1;
        exit;
      end;
      WM_DESTROY:
      begin
        PostQuitMessage(0);
        Result := 0;
        Exit;
      end;
      WM_PAINT:
      begin
        BeginPaint(WinHandle, ps);
        SkinGrid.DrawGrid(WinHandle);
        EndPaint(WinHandle, ps);
        Result := 0;
        Exit;
      end;
    end;
    Result := DefWindowProc(WinHandle, Msg, wP, lP);
  end; // end SkinEngine

end;

destructor TSkinGrid.Destroy;
begin

  inherited Destroy;
end;

procedure TSkinGrid.DrawGrid(WinHandle: HWND);
var
  graphics: Cardinal;
  pen:     Integer;
  IntI:    Integer;
  DC:      HDC;
  rc:      TRect;

begin
  with SkinEngine do
  begin
    // Initialisierern
    DC := GetDC(WinHandle);

    GetClientRect(WinHandle, rc);

    GdipCreateFromHDC(DC, graphics);
    GdipCreatePen1(ColorARGB(255, RGB(0, 0, 0)), 1, UnitPixel, pen);

    for IntI := 0 to rc.Right do
    begin
      if IntI mod FOffsetX <> 0 then continue;
        GdipDrawLineI(graphics, pen, IntI, 0, IntI, rc.Bottom);
    end;

    for IntI := 0 to rc.Bottom do
    begin
       if IntI mod FOffsetY <> 0 then continue;
         GdipDrawLineI(graphics, pen, 0, IntI, rc.Right, IntI);
    end;

    // Freigeben
    GdipDeletePen(pen);
    GdipDeleteGraphics(graphics);
    ReleaseDC(WinHandle, DC);
  end;

end;

function TSkinGrid.GetHandle: hWnd;
begin

  result := FhGrid;
end;

function TSkinGrid.GetOffsetX: Integer;
begin

  Result := FOffsetX;
end;

function TSkinGrid.GetOffsetY: Integer;
begin

  Result := FOffsetY;
end;

end.
Delphi-Quellcode:
SkinGrid := @FHGrid;

Mußte ich auf die Classe casten weil ich sonst ein problem mit den Variablen in der WinProc habe.

Zitat:

Hast du eventuell eine gleichnamige lokale Variable zu deiner eventuell vorhandenen globalen Variable?
Denke nicht.
Aber der zähler ist auf 0 .. kann man auf dem bild auch sehen.

EDIT:
Wenn ich jetzt eine globale Variable definiere.
Zitat:

mOffsetX : Integer;
mOffsetY : Integer;
und übergebe dieser die Variable welche noch gültig ist beim start
dann funktioniert es.

Zitat:

mOffsetX := FOffsetX;
mOffsetY := FOffsetY;

Nur welchen Sinn haben dann die Variablen die ich in der Classe definiert habe wenn sie nicht funktionieren.
Bzw.. das Interface vorher zerstört wird.


gruss

Uwe Raabe 22. Mär 2011 07:14

AW: Warum zerstören sich meine Classen
 
Definiere doch mal (und wenn auch nur zum Testen) folgende Variable:

Delphi-Quellcode:
var
  FPrevClientProc: TFNWndProc;
  SkinGrid : TSkinGrid;
  SkinGridIntf: ISkinGrid;
Dann erzeugst du das SkinGrid mit

Delphi-Quellcode:
SkinGridIntf := TSkinGrid.Create(...);
und schau mal, ob es dann geht.

Sorry, aber deine Art mit Klassen, Interfaces und Handles zu hantieren ist irgendwie, sagen wir "unüblich".

Wenn du die Referenzzählung nicht brauchst, dann leite deine Klassen nicht von TInterfacedObject sonder von TInterfacedPersistent (classes.pas) ab. Dann musst du die Instanzen aber auch selbst wieder freigeben.

Blup 22. Mär 2011 08:41

AW: Warum zerstören sich meine Classen
 
Diese Variablen werden überschrieben, sobald es mehr als eine Instance von TSkinGrid gibt:
Delphi-Quellcode:
var
  FPrevClientProc: TFNWndProc;
  SkinGrid : TSkinGrid;
Deshalb müssen diese Member der Klasse sein.
In der Funktion GridProc soll auf die jeweilige Instanz von TSkinGrid zugegriffen werden.
Benötigt wird eine List aller Instanzen, um sich auf Grund des Handle die richtige zu ermitteln.

Das Interface und die implementierende Klasse in der selben Unit zu deklarieren ist zumindest fragwürdig.
Aus welchen Gründen wird hier überhaupt mit einem Interface gearbeitet?

Ich würde TSkinGrid von TComponent ableiten und beim Constructor als Owner die jeweils das skinnende Objekt übergeben.
Damit hat das TSkinGrid die selbe Lebensdauer wie der Owner und es kann auch auf Owner zugegriffen werden.

QuickAndDirty 22. Mär 2011 11:13

AW: Warum zerstören sich meine Classen
 
Ich nehme an er nimmt interfaces um später mal Skins aus DLLs importieren zu können. ???

EWeiss 22. Mär 2011 11:36

AW: Warum zerstören sich meine Classen
 
Delphi-Quellcode:
Aus welchen Gründen wird hier überhaupt mit einem Interface gearbeitet?

Weil meine Objecte(Controls oder wie auch immer) sich in einer DLL befinden.
Und ich von außen auf die später Mitgelieferte API.. der DLL zugreife.

Wie also soll ich das komplette Object von außen Aufrufen ohne Interface?

Delphi-Quellcode:
    BoxGrid := CTRL_GridCreate(hMain, SKAERO_FOLDER +
      'Grid.png', 150, 67, 585, 257, 20, 10, ID_BOXGRID);
    SKAERO_SetAnchorMode(BoxGrid.Handle, ANCHOR_HEIGHT_WIDTH);
    SKAERO_SetZorder(BoxGrid.Handle, HWND_TOP);
Das ist in der Anwendung...
Der rest in einer DLL
Warum soll der User der meine DLL verwenden möchte sich mit GDI+ und konsorte rumquälen
wenn die DLL das später alles zur verfügung stellt.


Delphi-Quellcode:
function CTRL_GridCreate(hOwner: HWND; FullpathImageName: string;
  x, y, xW, yH, OffsX, OffsY, ButID: Integer): ISkinGrid; stdcall;
begin

  result := TSkinGrid.Create(hOwner, FullpathImageName, x, y, xW, yH,
    OffsX, OffsY, ButID);
end;

Zitat:

FPrevClientProc: TFNWndProc;

Habe ich wieder entfernt wollte die GridProc Subclassen
ist aber in dem Fall nicht nötig.

gruss

rollstuhlfahrer 22. Mär 2011 11:43

AW: Warum zerstören sich meine Classen
 
Es hängt ja nicht daran, wo was ist und für was es verwendet werden soll, sondern wie die Typen gebraucht werden. Für ein Interface gibt es einen automatischen Referenzzähler (also ein Garbage Collector für Delphi, der funktioniert). Dieser funktioniert allerdings nur dann korrekt, wenn man keine Objekt-Typen mehr verwendet, sondern nur noch Interface-Typen.

2. Stoplerstein: Wenn ein Interface keiner Variablen mehr zugeordnet ist, dann heißt das automatisch, dass das Interface weg muss (Garbage Collector). Dazu im Gegensatz das Nicht-Interface-Objekt: Das verschwindet erst, wenn jemand explizit Free (Destroy) aufgerufen hat.

Bernhard

PS: Hoffe, alles nochmal zusammengefasst und richtig dargestellt zu haben.

EWeiss 22. Mär 2011 11:58

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1090234)
Es hängt ja nicht daran, wo was ist und für was es verwendet werden soll, sondern wie die Typen gebraucht werden. Für ein Interface gibt es einen automatischen Referenzzähler (also ein Garbage Collector für Delphi, der funktioniert). Dieser funktioniert allerdings nur dann korrekt, wenn man keine Objekt-Typen mehr verwendet, sondern nur noch Interface-Typen.

2. Stoplerstein: Wenn ein Interface keiner Variablen mehr zugeordnet ist, dann heißt das automatisch, dass das Interface weg muss (Garbage Collector). Dazu im Gegensatz das Nicht-Interface-Objekt: Das verschwindet erst, wenn jemand explizit Free (Destroy) aufgerufen hat.

Bernhard

PS: Hoffe, alles nochmal zusammengefasst und richtig dargestellt zu haben.

Danke das habe ich jetzt verstanden.

Wie Uwe schon sagt...
Zitat:

Sorry, aber deine Art mit Klassen, Interfaces und Handles zu hantieren ist irgendwie, sagen wir "unüblich".

Er hat schon recht aber letztendlich zählt das ergebnis wie man dahin kommt ist eine andere sache.
Ich verwende jetzt TInterfacedPersistent obwohl mir der unterschied nicht geläufig ist abgesehen davon das sie keinen Referenzzähler hat
Damit funktioniert es.

Wie muß ich das nun korrekt freigeben?
Bedeutet das ich müßte eine Free Methode nach außen weiterleiten?


gruss

rollstuhlfahrer 22. Mär 2011 12:01

AW: Warum zerstören sich meine Classen
 
Der GC macht ja nichts anderes als .Free aufzurufen, wenn keine Instanzen mehr vorhanden sind. Wenn du jetzt den Referenzzähler nicht benutzt, brauchst du eine Methode, die zumindest intern .Free aufruft. Du kannst aber auch das Free über dein Interface nach außen geben.

Bernhard

EWeiss 22. Mär 2011 12:07

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1090237)
Der GC macht ja nichts anderes als .Free aufzurufen, wenn keine Instanzen mehr vorhanden sind. Wenn du jetzt den Referenzzähler nicht benutzt, brauchst du eine Methode, die zumindest intern .Free aufruft. Du kannst aber auch das Free über dein Interface nach außen geben.

Bernhard

Ja verstehe ich nur "Free" muss ja irgendetwas machen. ;)

Mit TInterfacedPersistent wird jetzt kein Destroy mehr aufgerufen.
Wie muss die Funktion Free also aussehen?

gruss

rollstuhlfahrer 22. Mär 2011 12:11

AW: Warum zerstören sich meine Classen
 
.Free ist eine Methode deines OBJEKTES und diese Methode existiert weiterhin. Da sie in TObject definiert worden ist, sollte es kein Problem sein, diese zu verwenden.

Was sie macht: Nach einer Prüfung, ob das Objekt überhaupt existiert, wird Destroy veranlasst.

Bernhard

EWeiss 22. Mär 2011 12:20

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1090242)
.Free ist eine Methode deines OBJEKTES und diese Methode existiert weiterhin. Da sie in TObject definiert worden ist, sollte es kein Problem sein, diese zu verwenden.

Was sie macht: Nach einer Prüfung, ob das Objekt überhaupt existiert, wird Destroy veranlasst.

Bernhard

Sorry ich habe kein TObject sondern TInterfacedPersistent.
Deshalb auch meine Frage.

gruss

rollstuhlfahrer 22. Mär 2011 12:26

AW: Warum zerstören sich meine Classen
 
Natürlich hast du immer ein Objekt, da man Klassen nur ableiten kann und die Grundklasse, die immer dabei ist ist TObjekt.

Du kannst dir das wie eine Hierarchie vorstellen und an der Spitze steht immer TObject.

Bernhard

EWeiss 22. Mär 2011 12:35

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1090246)
Natürlich hast du immer ein Objekt, da man Klassen nur ableiten kann und die Grundklasse, die immer dabei ist ist TObjekt.

Du kannst dir das wie eine Hierarchie vorstellen und an der Spitze steht immer TObject.

Bernhard

Procedure Free: TObject; ?

Das wollte ich gerne wissen.
Wenn ich Free nach außen weiterleite muss die Anwendung doch wissen was sie damit tun soll..
Bzw auf was sie verzweigt.

gruss

rollstuhlfahrer 22. Mär 2011 12:41

AW: Warum zerstören sich meine Classen
 
Falsche Richtung.

Delphi-Quellcode:
type
  IMyInterface = interface(IUnknown)
  public
    // ...
    procedure Free;
  end;
So war das gemeint. Du sollst nicht das Objekt irgendwo hin geben, sondern wo anders die Möglichkeit anbieten, das Objekt zu löschen.

Bernhard

EWeiss 22. Mär 2011 13:04

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1090250)
Falsche Richtung.

Delphi-Quellcode:
type
  IMyInterface = interface(IUnknown)
  public
    // ...
    procedure Free;
  end;
So war das gemeint. Du sollst nicht das Objekt irgendwo hin geben, sondern wo anders die Möglichkeit anbieten, das Objekt zu löschen.

Bernhard

Sorry wenn ich nochmal blöd frage..
Es reicht in meiner Classe ein einfaches procedure Free zu deklarieren?
Und die ruft dann Tobject vom Interface TInterfacedPersistent auf.

Delphi-Quellcode:
type
  ISkinGrid = interface
    ['{89A97429-5E4B-43B6-87D8-381DD4E8CF21}']
    function GetHandle: hWnd;
    property Handle: hWnd read GetHandle;
    procedure Free;
  end;

Hmm etwas unverständlich.
Ja ich lerne es noch mit den Interfacen.

EDIT:
Es funktioniert auf jedenfall.
Danke für eure Hilfe!

gruss

rollstuhlfahrer 22. Mär 2011 14:04

AW: Warum zerstören sich meine Classen
 
So grob stimmt das. Du definierst ein Free in deinem Interface und schon ist es zugänglich. Free ist bei deinem Objekt schon definiert und zieht mit deinem TInterfacedPersistent ein (passiert auch bei TInterfacedObject). Free sorgt dafür, dass das Objekt verschwindet. Heißt also: Von außen Free aufrufen und weg ist das Objekt.

Bernhard

ADD: Eben so, als würdest du das Objekt vor dir haben.

EWeiss 22. Mär 2011 14:14

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1090261)
So grob stimmt das. Du definierst ein Free in deinem Interface und schon ist es zugänglich. Free ist bei deinem Objekt schon definiert und zieht mit deinem TInterfacedPersistent ein (passiert auch bei TInterfacedObject). Free sorgt dafür, dass das Objekt verschwindet. Heißt also: Von außen Free aufrufen und weg ist das Objekt.

Bernhard

ADD: Eben so, als würdest du das Objekt vor dir haben.

Danke für deine Erklärung..
Überlege nun ob ich alle Interface nach TInterfacedPersistent umlege.
Das verhindert zumindest das sie selbst zerstört werden.

In wie weit sich das jetzt auf Speicher usw.. bemerkbar macht weiss ich allerdings nicht.
Denke da könnte einiges zusammen kommen wenn diese während der laufzeit nicht freigegeben werden.

Da ist eure Meinung gefragt. :)

gruss

rollstuhlfahrer 22. Mär 2011 14:31

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von EWeiss (Beitrag 1090263)
Da ist eure Meinung gefragt.

Meine Meinung? - Einfach die Interfaces richtig verwenden und schon klappt das.

Bernhard

Patito 22. Mär 2011 14:44

AW: Warum zerstören sich meine Classen
 
Boa, seid ihr alle gruselig... :pale::pale:

1) Wer versucht Free in ein Interface aufzunehmen hat die zugrundeliegende Problematik von Interfaces in Delphi nicht verstanden - sowas führt auf direktem Weg zu einer AV: 6 - setzen!
Prüft mal eure Programme auf Zugriffe auf freigegebenen Speicher...

2) Objekte mit Interfaces zerstören sich nicht selber wenn der RefCount 0 wird.
Es wird lediglich _Release() aufgerufen.
Nur wenn man von einer Klasse ableitet, die in _Release() den Destructor aufruft (z.B. TInterfacedObject) zerstört sich das Object bei RefCount 0.

3) Objekte freigeben, auf die es noch irgendwelche Interface-Referenzen gibt ist *VERBOTEN*.
Tut man es trotzdem, wird später wenn die Interface-Referenz gelöscht wird das _Release() des bereits freigegebenen Objektes aufgerufen.

Zur Lösung des Problems: Vermutlich hilft hier eine Wrapper-Klasse, die sich um die Erstellung und das Aufräumen kümmert.
Z.B. wäre es auch ganz nett die zugehörige Arbeit zum Erstellen und Aufräumen innerhalb der DLL in eigene Init und Exit Prozeduren (ohne Interfaces) auszulagern.

rollstuhlfahrer 22. Mär 2011 14:52

AW: Warum zerstören sich meine Classen
 
Ich sagte doch: Interfaces richtig benutzen. Das hier ist ein Quick&Dirty, vor allem Dirty, Workaround, der es dem TE erleichtern soll, das ganze zu managen, weil scheinbar immernoch ein paar Probleme mit Interfaces und deren Benutzung existieren.

Bernhard

EWeiss 22. Mär 2011 15:01

AW: Warum zerstören sich meine Classen
 
Zitat:

weil scheinbar immernoch ein paar Probleme mit Interfaces und deren Benutzung existieren.
Dann erkläre es mir doch wenn es nicht zuviel von deiner Zeit in Anspruch nimmt.
Der TE ist kein professioneller Programmierer und schon gar nicht Informatiker.
Berücksichtige das Bitte!

Ich stelle nur Fragen wenn Sie beantwortet werden freut es mich natürlich.
Soll aber nicht heißen das jemand für mein Hobby (Arbeiten soll).

Es ist der Sinn eines Forums das man sich dort informiert um zu lernen.
Und was an meiner letzten Frage jetzt so unverständlich war bzw.. was es damit zu tun hat es mir leichter zu machen
verstehe ich jetzt nun wirklich nicht.

Ich habe gefragt ob sich das ändern der Interface auf den Speicher auswirkt.
Was war da nun so tragisch :?:

gruss

rollstuhlfahrer 22. Mär 2011 15:08

AW: Warum zerstören sich meine Classen
 
das soll jetzt aber nicht zum persönlichen Angriff mutieren. Außerdem hatte ich gedacht, dass die bis jetzt erarbeitete Lösung so halbwegs funktioniert und deinen Ansprüchen fürs erste genügt. Ich habe mich noch nie damit beschäftigt, wie man Interfaces einsetzt um ganze Objekte zwischen DLL und EXE auszutauschen, ich kann also nur Tipps geben, wie und ob das funktioniert, kann ich nicht 100%ig sagen.

Bernhard

PS: Es klingt nur für mich komisch, dass die zuerst angesprochene Version nicht funktioniert, wobei die gerade das Non-Plus-Ultra ist.

EWeiss 22. Mär 2011 15:10

AW: Warum zerstören sich meine Classen
 
Zitat:

das soll jetzt aber nicht zum persönlichen Angriff mutieren.
Nicht falsch verstehen... Auf keinen Fall
Das war kein Angriff auf deine Person.

Danke nochmal für deine Hilfe.

PS:
Möchte halt nur verstehen wie das alles zusammenhängt.
Wo soll ich denn fragen wenn nicht hier ;)

gruss

Blup 23. Mär 2011 08:56

AW: Warum zerstören sich meine Classen
 
Free in das Interface aufzunehmen oder das Objekt über eine andere Methode des Interface freizugeben ist problematisch. Es existiert zu diesem Zeitpunkt zumindest diese eine Interfacevariable. Danach wird irgendwann der Gültigkeitsbereich für diese Variable verlassen, das übergeordnete Objekt freigegeben, bzw. der Interface-Variable NIL oder ein anderer Wert zugewiesen.
Dabei wird automatisch über das Interface "_Release" des implementierenden Objects aufgerufen.
Delphi-Quellcode:
function TInterfacedPersistent._Release: Integer;
begin
  if FOwnerInterface <> nil then
    Result := FOwnerInterface._Release else
    Result := -1;
end;
Da der versteckt übergebene Parameter Self auf ein nicht mehr existierendes Objekt verweist, kann der implizite Zugriff auf Self.FOwnerInterface zur Zugriffsverletzung führen.

EWeiss 23. Mär 2011 14:08

AW: Warum zerstören sich meine Classen
 
Zitat:

Zitat von Blup (Beitrag 1090407)
Free in das Interface aufzunehmen oder das Objekt über eine andere Methode des Interface freizugeben ist problematisch. Es existiert zu diesem Zeitpunkt zumindest diese eine Interfacevariable. Danach wird irgendwann der Gültigkeitsbereich für diese Variable verlassen, das übergeordnete Objekt freigegeben, bzw. der Interface-Variable NIL oder ein anderer Wert zugewiesen.
Dabei wird automatisch über das Interface "_Release" des implementierenden Objects aufgerufen.
Delphi-Quellcode:
function TInterfacedPersistent._Release: Integer;
begin
  if FOwnerInterface <> nil then
    Result := FOwnerInterface._Release else
    Result := -1;
end;
Da der versteckt übergebene Parameter Self auf ein nicht mehr existierendes Objekt verweist, kann der implizite Zugriff auf Self.FOwnerInterface zur Zugriffsverletzung führen.

Habe auf grund ähnlicher vermutung die Free proceduren auch wieder entfernt.
Denke das Windows das Automatisch übernimmt wenn das Programm geschlossen wird.

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:46 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