Announcement

Collapse
No announcement yet.

Zugriffsverletzung bei TForm.Release am Ende der DLL

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Zugriffsverletzung bei TForm.Release am Ende der DLL

    Hallo,

    meine DLL besitzt u.A. ein Formular als Statusanzeige mit Progressbar usw. Nach dem Ausführen der Funktion sollte das Formular mit TForm.Release freigegeben werden. Bei dieser Aktion kommt es aber zu dieser unschönen Meldung:

    "Zugriffsverletzung bei Adresse 0152228C in Modul 'Modulname.DLL'. Lesen von Adresse FFFFFFFF."

    WARUM? Wie kann ich das lösen? Blockiert noch irgendwo, irgendetwas?

    Für Hilfe wäre ich sehr dankbar!!!
    Gruß
    AJS

    Hier auch der Quellcode aus der DLL:

    procedure FileConv(inPath: pChar);stdcall;
    begin
    { zuerst Form erstellen }
    Form_Conv_DLL:= TForm_Conv_DLL.Create(nil);

    try
    begin
    Form_Conv_DLL.Show;
    Form_Conv_DLL.iniPath.Caption := inPath;
    Form_Conv_DLL.Start;
    end;
    finally
    Form_Conv_DLL.Release;
    end;

    end;

  • #2
    Hallo,

    ich kann diesen Effekt bei mir (Delphi 5.01; Windows 2000 Professional) nicht nachvollziehen. Das folgende Beispiel verhält sich so wie gewünscht:

    <b>DLL-Projektdatei</b>:
    <pre>
    library DLLProgressBarForm;

    uses
    SysUtils,
    Classes,
    DLLProgressBarFormFrm in 'DLLProgressBarFormFrm.pas' {Form1};

    {$R *.RES}

    exports
    ShowDLLForm;

    begin
    end.
    </pre>
    <b>DLL-Formularunit:</B>
    <pre>
    unit DLLProgressBarFormFrm;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    ComCtrls;

    type
    TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    private
    { Private-Deklarationen }
    procedure Start;
    public
    { Public-Deklarationen }
    end;

    var
    Form1: TForm1;

    procedure ShowDLLForm;

    implementation

    {$R *.DFM}

    { TForm1 }

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caHide;
    end;

    procedure TForm1.Start;
    var
    i : Integer;
    begin
    for i := 1 to 10 do
    begin
    ProgressBar1.Position := ProgressBar1.Position + 10;
    Sleep(100);
    end;
    end;

    { DLL-Schnittstellenprozedur }

    procedure ShowDLLForm;
    begin
    Form1 := TForm1.Create(nil);
    try
    Form1.Show;
    Form1.Start;
    finally
    Form1.Release;
    end;
    end;

    end.
    </pre>
    <b>Aufruf im Client:</b>
    <pre>
    procedure ShowDLLForm; external 'DLLProgressBarForm.dll';

    procedure TForm2.Button1Click(Sender: TObject);
    begin
    ShowDLLForm;
    end;
    </pre>
    Mit dem Aufruf von <b>Release</b> wird über <i>PostMessage(Handle, CM_RELEASE, 0, 0);</i> eine eigene Botschaft in der Botschaftswarteschlange abgelegt. Da Borland <b>PostMessage</b> (und nicht SendMessage) verwendet, sollte diese Botschaft erst dann verarbeitet werden, wenn alle "wichtigen" Windows-Sachen bereits gelaufen sind

    Comment


    • #3
      Danke Herr Kosch!

      Ich habe meinen Code nach Ihrer Anregung ein wenig umgestellt, sodass die DLL jetzt ohne Fehlermeldung beendet wird. Allerdings kann ich die Form nicht mit Release freigeben, da dann immer noch die gleiche Meldung erscheint. Mit TForm.Free geht es aber. Das habe ich davor auch schon versucht gehabt, ging aber nicht.

      Fazit: keine Ahnung. Ich denke, eine Komponente oder Ähnliches wird noch benutzt bzw. wird nicht richtig freigegenen und das führt bei dem Versuch die Form mit Release freizugeben zum Absturz.

      Sei wie es ist, vielen Dank für Ihre Hilfe!
      Gruß
      AJ

      Comment


      • #4
        Hi Andreas

        "Mit dem Aufruf von Release wird über PostMessage(Handle, CM_RELEASE, 0, 0); eine eigene Botschaft in der Botschaftswarteschlange abgelegt. Da Borland PostMessage (und nicht SendMessage) verwendet, sollte diese Botschaft erst dann verarbeitet werden, wenn alle "wichtigen" Windows-Sachen bereits gelaufen sind"

        Geschiet auch so, bei dem Entladen einer DLL kann es aber vorkommen das ALLE wichtigen Units wie Controls/Forms schon "finalisiert" wurden und erst danach die cm_Release Message ausgeführt wird. Dadurch greift der destructor TForm.Destroy auf eine Application/Screen variable zu die schon längst freigegeben wurde. Resultat ist eine Schutzverletzung die falls SysUtils schon "finalisiert" wurde, also das Exceptionhandling, in einem RunError() mündet. .Release ist also definitiv hier unangebracht und nur .Free funktioniert korrekt aber eben hart.
        .Release sollte NUR verwendet werden, wenn auch Application.Run; aufgerufen wird, und das ist in einer DLL nicht der Fall.

        Gruß Hage

        Comment

        Working...
        X