Moin,
ich habe eine
DLL geschrieben, auf die gleichzeitig von Delphi- und VBA-Programmen zugegriffen wird. Der Zugriff geschieht dabei grundsätzlich über exportierte Funktionen und Prozeduren.
Innerhalb dieser
DLL habe ich eine Klasse von TObject abgeleitet, die für die Datenbankzugriffe zuständig ist. Dafür sind zwei Prozeduren zuständig: eine für die Anmeldung an der Datenbank, die andere für die Abmeldung.
Delphi-Quellcode:
procedure ConnectDB(cPServer, cPUser : PAnsiChar);
stdcall;
var
cServer: AnsiString;
cDBUser : AnsiString;
begin
cServer := AnsiString(cPServer);
cDBUser := AnsiString(cPUser);
try
if not Assigned(dmDLLPenta)
then begin
dmDLLPenta := TdmPenta.Create();
end;
dmDLLPenta.ConnectDB(
String(cServer),
String(cDBUser));
except on E :
Exception do begin
Warning('
Fehler bei Verbindungsaufbau: ' + E.
Message);
end;
end;
end;
procedure DisConnectDB( );
stdcall;
begin
if Assigned(dmDLLPenta)
then begin
dmDLLPenta.DisConnectDB();
FreeAndNil(dmDLLPenta);
end;
end;
Die beiden Methoden ConnectDB und DisConnectDB sowie die Klasse sehen wie folgt aus:
Delphi-Quellcode:
TdmPenta =
class(TObject)
private
oPS : TPentaSettings;
cDBUser :
String;
oPenta : TPenta;
public
osnPenta : TOraSession;
qryAbf : TOraQuery;
constructor Create();
reintroduce;
destructor Destroy();
override;
procedure ConnectDB(cServer, cUser :
String);
procedure DisConnectDB();
end;
constructor TdmPenta.Create();
begin
inherited;
oPenta := TPenta.Create();
oPS := TPentaSettings.Create();
osnPenta := TOraSession.Create(
nil);
qryAbf := TOraQuery.Create(
nil);
qryAbf.Session := osnPenta;
end;
destructor TdmPenta.Destroy;
begin
try
FreeAndNil(qryAbf);
FreeAndNil(osnPenta);
// <==== Problemstelle
FreeAndNil(oPS);
if Assigned(oPenta)
then begin
FreeAndNil(oPenta);
end;
except on E :
Exception do begin
dbg('
FSGVBA - Destroy Fehler aufgetreten: ' + E.
Message);
end;
end;
inherited;
end;
procedure TdmPenta.ConnectDB(cServer, cUser:
String);
begin
if not Assigned(oPenta)
then begin
oPenta := TPenta.Create();
end;
if not Assigned(osnPenta)
then begin
osnPenta := TOraSession.Create(
nil);
end;
if not Assigned(qryAbf)
then begin
qryAbf := TOraQuery.Create(
nil);
qryAbf.Session := osnPenta;
end;
DBUser := cUser;
osnPenta.Server := cServer;
osnPenta.Username := cUser;
osnPenta.Password := '
xxxx';
Settings.GetSettings(cUser);
osnPenta.Connected := true;
if Assigned(oPenta)
then begin
oPenta.DBSession := osnPenta;
end;
end;
In den Delphi-Programmen habe ich jetzt das Problem, dass beim Beenden des Programmes im
Debugger eine
Exception (
Access Violation at adress ....) am Ende der
DLL-Freigabe geworfen wird, die im Aufrufstack bei System.Halt() anfängt und irgendwo weiter oben tatsächlich auch Adressen im Oracle-Client aufweist.
Wird die Problemstelle auskommentiert, beendet sich das Programm ohne jeglichen Fehler.
Es ist keine
Exception zu sehen, wenn das
Programm ohne Debugger gestartet wird!
Die Datenbankconnection wird in beiden Fällen trotzdem geschlossen.
1) Sowohl Create als auch Destroy der dmDLLPenta werden nur 1x aufgerufen!
2) Die Session ist während des Programmlaufs vollkommen i.O. Datenbankabfragen werden ohne jegliche Probleme ausgeführt. Der Ärger fängt erst an, wenn das Programm (im Debugger!) geschlossen wird.
3) Ich habe u.a. auch eine DllProc hinterlegt, die mir den DLL_PROCESS_DETACH meldet. Diese Meldung kommt vor der
Exception
4) Verwendet werden die ODAC-Komponenten von Devart in Version 11.1.3 für Delphi 10.3 und 12.0.2 für Delphi 11.0, es passiert dasselbe in beiden Versionen.
Ich bin inzwischen ziemlich ratlos, was da schief geht. Irgendjemand Hinweise?
Gruß
hsg