Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Zugriffsverletzung bei DLL-Benutzung (https://www.delphipraxis.net/123101-zugriffsverletzung-bei-dll-benutzung.html)

bianfable 27. Okt 2008 18:46


Zugriffsverletzung bei DLL-Benutzung
 
Hallo Leute!

Ich habe heute zum ersten mal das Programmieren mit DLLs ausprobiert und musste leider feststellen, dass es zu einer Zugriffsverletzung beim Schließen des Programms mit der DLL kommt. Es werden KEINE STRINGS übergeben, da ich bereits gelesen habe, dass das zu Problemen führen kann! Ich habe außerdem noch den Ratschlag von Delphi befolgt "Sharemem" zu den Uses der Unit UND des Projekts hinzuzufügen! Die DLL liegt auch im Stammverzeichnis des Projekts!

Hier ist der Ausschnitt aus der DLL, den ich verwende:
Delphi-Quellcode:
library Bianfable;

uses
  SysUtils, Classes, Windows, Messages, Graphics, Controls,
  Forms, Dialogs, StdCtrls, IniFiles, JPEG, ShellAPI, Menus;

procedure CenterWindow(F: TForm); stdcall;
begin
  F.Left := Screen.Width div 2 - F.Width div 2;
  F.Top := Screen.Height div 2 - F.Height div 2;
end;

//...

exports
  CenterWindow,
  //...;

begin
end.
So deklariere ich die Prozedur aus der DLL in meinem Hauptprogramm:
Delphi-Quellcode:
type
  //...

procedure CenterWindow(F: TForm); stdcall; external 'Bianfable.dll';

var
  //...
Und so benutze ich die Prozedur schließlich:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  CenterWindow(Form1);
end;
Wär echt nett, wenn ihr mir sagen könntet, was ich noch falsch mache...

Bianfable...

DeddyH 27. Okt 2008 18:51

Re: Zugriffsverletzung bei DLL-Benutzung
 
Du kannst keine VCL-Objekte zwischen DLL und Applikation austauschen. Dazu bräuchtest Du eine *.bpl

bianfable 27. Okt 2008 18:54

Re: Zugriffsverletzung bei DLL-Benutzung
 
Ist eine Form den eine VCL-Komponente???

Außerdem gibts die Fehlermeldung ja beim beenden des Programms, die eigentliche Verwendung des Quelltextes ist da eigentlich schon abgeschlossen (erfolgreich)!

DeddyH 27. Okt 2008 19:05

Re: Zugriffsverletzung bei DLL-Benutzung
 
Ja, eine Form ist auch eine VCL-Komponente. Du könntest aber z.B. das Handle der Form an die DLL übergeben und in der DLL damit arbeiten, das sollte keine Probleme geben.

SirThornberry 27. Okt 2008 19:23

Re: Zugriffsverletzung bei DLL-Benutzung
 
Es geht nicht nur um VCL-Komponenten sondern generell um Objecte. Das der Fehler erst beim Beenden kommt hast du richtig erkannt. Problem ist das die DLL und deine Anwendung getrennte Speichermanager verwenden. Beim Beenden versuchen diese den Speicher frei zugeben und da kommt es zu Fehlern weil der eine Speichermanager versucht Dinge frei zu geben die er gar nicht angefordert hat.
Aber man sollte generell keine Objecte zwischen DLL und Anwendung austauschen. Dafür gibt es BPLs. Diese haben den Vorteil das sicher gestellt wird das die Objecte in der DLL(BPL) identisch mit denen außerhalb der DLL(BPL) sind. Denn bei normaler Verwendung per DLL stellt ja niemand sicher das ein Object aus der DLL von der gleichen Delphiversion mit dem gleichen Speicheraufbau stammt.

bianfable 28. Okt 2008 16:01

Re: Zugriffsverletzung bei DLL-Benutzung
 
Ok...vielen Dank!!!

Cyf 28. Okt 2008 17:20

Re: Zugriffsverletzung bei DLL-Benutzung
 
Zitat:

Zitat von SirThornberry
Es geht nicht nur um VCL-Komponenten sondern generell um Objecte. Das der Fehler erst beim Beenden kommt hast du richtig erkannt. Problem ist das die DLL und deine Anwendung getrennte Speichermanager verwenden. Beim Beenden versuchen diese den Speicher frei zugeben und da kommt es zu Fehlern weil der eine Speichermanager versucht Dinge frei zu geben die er gar nicht angefordert hat.
Aber man sollte generell keine Objecte zwischen DLL und Anwendung austauschen. Dafür gibt es BPLs. Diese haben den Vorteil das sicher gestellt wird das die Objecte in der DLL(BPL) identisch mit denen außerhalb der DLL(BPL) sind. Denn bei normaler Verwendung per DLL stellt ja niemand sicher das ein Object aus der DLL von der gleichen Delphiversion mit dem gleichen Speicheraufbau stammt.

Hatte (da ich eigentlich noch nie Objekte in einer dll gebraucht habe) das Problem zwar nocht nicht, aber kannst du das bitte nochmal genauer ausführen? Wie sieht es zum Beispiel mit einer einfachen von TObject abgeleiteten Klasse aus, die nicht ausgetauscht wird, sondern einfach nur in der dll verwendet wird?

igel457 28. Okt 2008 17:33

Re: Zugriffsverletzung bei DLL-Benutzung
 
Ich verstehe nicht warum, immer alle sagen, zwischen DLL und Host könnten keine Objekte ausgetauscht werden. In meiner 2D Bibliothek mache ich das ständig und das funktioniert einwandfrei. Wer es nicht glauben kann schaut hier nach:

DLL-Hauptunit:
http://andorra.cvs.sourceforge.net/v...22&view=markup

DLL-Klassenimplementierungen:
http://andorra.cvs.sourceforge.net/v...53&view=markup

Die einzige Einschränkung, die mir bis jetzt aufgefallen ist, ist die Tatsache, dass man nicht auf die RTTI Informationen der im Plugin erzeugten Objekte zugreifen kann und das man in der DLL keine größeren Speicherbereiche reservieren kann, auf die dann die Hostapplikation zugreifen darf. In die andere Richtung geht jedoch auch das einwandfrei.

Ich schätze das die BPLs zum großen Teil nur das Problem mit den RTTI Informationen beheben.

Daher vermute ich, dass das hier geschilderte Problem von den in der DLL verwendeten Units kommt, die beim Entladen der Bibliothek versuchen Finalisierungsarbeiten auszuführen, die dann (also in der Bibliothek) jedoch nicht funktionieren.

Apollonius 28. Okt 2008 20:23

Re: Zugriffsverletzung bei DLL-Benutzung
 
Ich sehe beim modulübergreifenden Arbeiten mit DLLs zwei Probleme.
1. Wenn Objekte Strings oder andere Sprachkonstrukte verwenden, die den Speichermanager nutzen. Besonders fies ist das bei Bibliotheken wie der VCL.
2. Wenn explizit oder implizit auf die RTTI zugegriffen wird. Ich habe hier mal einen Ersatz für den as-Operator gepostet, der das Problem umgeht. Mit externen Bibliotheken funktioniert er natürlich nicht. Interessanterweise verwendet Delphi selbst einen modifizierten is-Operator beim Exception-Handling mit der on-EWuppdi-do-Syntax, sodass es möglich sein sollte, modulübergreifend Exceptions zu fangen.

Worin ich ehrlich gesagt kein Problem sehe, ist das Allozieren und Freigeben von Objekten. Glücklicherweise sind nämlich TObject.Destroy und TObject.FreeInstance virtuell, sodass der richtige Speichermanager das Objekt freigibt.


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