![]() |
DLL Einbindung - Fehler beim Beenden
Moin!
Ich habe ein nettes kleines Tool geschrieben, womit man Einträge einer Tabelle ändern kann. --> Das funktioniert soweit. Jetzt gibt es noch ein paar weitere Programme die ähnliche Aufgaben erfüllen. Der Sicherheit halber habe ich jede Tabelle mit den gleichen Feldern erweitert und frage diese dann per DLL ab und zeige sie an. Funktioniert bis dahin auch ganz wunderbar... Wenn ich dann jedoch das Programm letztendlich beende (mit einem simplen "close"), kommt folgende Fehlermeldung: "Die Anweisung in xyz verweist auf Speicher in 123. Der Vorgang "read" konnte nicht auf dem Speicher ausgeführt werden." Danach kommt dann noch, "Runtime error 216 at xyz". Gestern habe ich das Internet bereits durchforstet nach Lösungen. Meine CPU ist nicht zu schnell und ich habe auch keinen SubSeven auf dem Rechner. Hat jemand eine weitere Idee? Sobald ich die Dll aus meinem Programm wieder entferne, geht alles wie vorher. Meine Frage lautet also: Was passiert eigentlich im Hintergrund wenn eine DLL aufgerufen wird? Innerhalb der DLL gebe ich alles was ich erzeugt habe auch wieder frei. Vielen Dank im vorraus! fsc |
Re: DLL Einbindung - Fehler beim Beenden
Lädst du die DLL dynamisch?
|
Re: DLL Einbindung - Fehler beim Beenden
nein sie ist statisch eingebunden. Es wird auch nur eine procedure aufgerufen, welche einer Datenbank Werte bzw Felder entnimmt und diese in ein StringGrid füllt.. dann modal anzeigt das wars
|
Re: DLL Einbindung - Fehler beim Beenden
Ist die DLL in Delphi geschrieben? Wurde ShareMem in DLL und Hauptprogramm verwendet?
Poste mal die Deklaratino der aufgerufenen Funktion. |
Re: DLL Einbindung - Fehler beim Beenden
die DLL habe ich mit Delhpi gemacht. ShareMem habe ich nicht verwendet.
Was macht ShareMem? :?: Dekalration unter Implemtation steht: ... procedure benutzer(Provider,feld,eintrag,einrag_detail:strin g)stdcall; external 'Aenderungsinfo.dll'; |
Re: DLL Einbindung - Fehler beim Beenden
Klassischer Fehler.
Sowohl in Hauptprogramm als auch DLL muss ShareMem eingebunden werden. DLL und Hauptprogramm haben sonst separate Memorymanager. Uebergibt und manipuliert man nun Strings oder Objekte (alles was dynamisch alloziiert ist), so wird Memory im einen Manager alloziiert und im anderen freigegeben. Das Resultat ist dann schnell ein korrumpierter Memorymanager und irgendwann (oft beim Programmende) gibt es einen Absturz. ShareMem verbindet beide Memorymanager so das es dann wieder einer ist. Erzeuge mal ein leeres DLL-Projekt mit Delphi und lies dir durch was im Kommentar des erzeugten Files steht. |
Re: DLL Einbindung - Fehler beim Beenden
Danke erstmal!
Also ShareMem habe ich eingebunden..., einfach nur in die uses Liste, nicht wahr? Jetzt erscheint beim schließen des aus der DLL heraus erzeugten Fensters eine Exception und beim Beenden einer dieser Windows Fehler: "Programm.exe hat einen Fehler verursacht" usw. Danach der Runtime error 217. Mit dem Datentyp ShortString und Pchar passiert das gleiche... EDIT: Muss die DLL wirklich als erste Unit eingebunden werden oder ist das quatsch?! |
Re: DLL Einbindung - Fehler beim Beenden
jawoll, die muss unbedingt als erste eingebunden werden.
Gruß onlinekater |
Re: DLL Einbindung - Fehler beim Beenden
das für zu einer Endlosschleife Exceptions nach beenden. erst 217 dann immer wieder 216.
|
Re: DLL Einbindung - Fehler beim Beenden
poste doch mal Deinen Code, vielleicht können wir Dir dann helfen.
Definitiv muß sharemem sowohl im aufrufenden Projekt (nicht in dessen Mainform oder sonstwo) als auch in der DLL als erstes in die USES-Klausel aufgenommen werden. Gruß onlinekater |
Re: DLL Einbindung - Fehler beim Beenden
Delphi-Quellcode:
Der Datenbankzugriff erfolgt über die SoapMemTable bzw SoapManager.
library Aenderungsinfo;
uses ShareMem, SysUtils, Dialogs, StdCtrls, Forms, Classes, Grids, kbmMemTable, uSOAPClient, QGraphics, Controls; {$R *.res} procedure benutzerdetails_anzeigen(provider,eindeutiges_feld,aktueller_eintrag,aktueller_eintrag_detail:string);stdcall; export; var Form1:TForm; StrGr_Aenderung:TStringgrid; SoapManager:TSoapManager; SMT_Table:TSoapMemTable; begin Form1:=TForm.Create(nil); Form1.Caption:='Datensatzdetails: '+aktueller_eintrag+' - '+aktueller_eintrag_detail; Form1.Position:=poScreenCenter; Form1.BorderStyle:=bsdialog; SoapManager:=TSoapManager.Create(nil); SoapManager.Active:=True; SMT_Table:=TSoapMemTable.Create(nil); SMT_Table.SOAPManager:=SoapManager; SMT_Table.ProviderName:=provider; SMT_Table.Active:=True; SMT_Table.Filtered:=True; SMT_Table.Filter:=eindeutiges_feld+'='''+aktueller_eintrag+''''; SMT_Table.Refresh; Form1.Height:=80; Form1.Width:=410; StrGr_Aenderung:=TStringgrid.Create(nil); with StrGr_Aenderung do begin Parent:=Form1; DefaultRowHeight:=20; Align:=alClient; if Form1.Height - Form1.ClientHeight > 28 then Form1.ClientHeight:=40 else Form1.ClientHeight:=45;//Form1.ClientHeight - (ClientHeight - Height); Form1.Width:=410; ColCount:=4; ColWidths[1]:=110; ColWidths[2]:=100; ColWidths[3]:=110; ColWidths[0]:=Width - ColWidths[1] - ColWidths[2] - ColWidths[3] - 7; RowCount:=2; FixedCols:=0; Cells[0,0]:=' Anlage von:'; Cells[1,0]:=' Anlagedatum:'; Cells[2,0]:=' Änderung von:'; Cells[3,0]:=' Änderungsdatum:'; Cells[0,1]:=SMT_Table.FieldbyName('benutzer_neu').asstring; Cells[1,1]:=SMT_Table.FieldbyName('datum_neu').asstring; Cells[2,1]:=SMT_Table.FieldbyName('benutzer_aend').asstring; Cells[3,1]:=SMT_Table.FieldbyName('datum_aend').asstring; StrGr_Aenderung.Options:= [goFixedHorzLine, goFixedVertLine, goHorzLine, goVertLine]; SMT_Table.Destroy; SoapManager.Destroy; end; try Form1.Update; Form1.ShowModal; finally Form1.Destroy; end; end; exports benutzerdetails_anzeigen; Im Hauptprogramm befindet sich ein ganz gewöhnlicher Prozedurenaufruf. Der Implementationteil steht bereits oben. Sharemem ist erster Eintrag in der uses Liste. |
Re: DLL Einbindung - Fehler beim Beenden
Hallo!
Du solltest Deine Objekte grundsätzlich nicht über Destroy sondern über Free zerstören. Free gibt nämlich auch den Speicher wieder frei. Außerdem hast Du StrGr_Aenderung nicht zerstört. Anbei nochmal Dein Code, mit Free. Ich habe außerdem das try-finally-Konstruct umgebaut, damit auch wirklich alles freigegeben wird.
Delphi-Quellcode:
Code ist ungetestet, da mir einige Units fehlen.
library Aenderungsinfo;
uses ShareMem, SysUtils, Dialogs, StdCtrls, Forms, Classes, Grids, kbmMemTable, uSOAPClient, QGraphics, Controls; {$R *.res} procedure benutzerdetails_anzeigen(provider,eindeutiges_feld,aktueller_eintrag,aktueller_eintrag_detail:string);stdcall; export; var Form1:TForm; StrGr_Aenderung:TStringgrid; SoapManager:TSoapManager; SMT_Table:TSoapMemTable; begin Form1:=TForm.Create(nil); SoapManager:=TSoapManager.Create(nil); SMT_Table:=TSoapMemTable.Create(nil); StrGr_Aenderung:=TStringgrid.Create(nil); try Form1.Caption:='Datensatzdetails: '+aktueller_eintrag+' - '+aktueller_eintrag_detail; Form1.Position:=poScreenCenter; Form1.BorderStyle:=bsdialog; SoapManager.Active:=True; SMT_Table.SOAPManager:=SoapManager; SMT_Table.ProviderName:=provider; SMT_Table.Active:=True; SMT_Table.Filtered:=True; SMT_Table.Filter:=eindeutiges_feld+'='''+aktueller_eintrag+''''; SMT_Table.Refresh; Form1.Height:=80; Form1.Width:=410; with StrGr_Aenderung do begin Parent:=Form1; DefaultRowHeight:=20; Align:=alClient; if Form1.Height - Form1.ClientHeight > 28 then Form1.ClientHeight:=40 else Form1.ClientHeight:=45;//Form1.ClientHeight - (ClientHeight - Height); Form1.Width:=410; ColCount:=4; ColWidths[1]:=110; ColWidths[2]:=100; ColWidths[3]:=110; ColWidths[0]:=Width - ColWidths[1] - ColWidths[2] - ColWidths[3] - 7; RowCount:=2; FixedCols:=0; Cells[0,0]:=' Anlage von:'; Cells[1,0]:=' Anlagedatum:'; Cells[2,0]:=' Änderung von:'; Cells[3,0]:=' Änderungsdatum:'; Cells[0,1]:=SMT_Table.FieldbyName('benutzer_neu').asstring; Cells[1,1]:=SMT_Table.FieldbyName('datum_neu').asstring; Cells[2,1]:=SMT_Table.FieldbyName('benutzer_aend').asstring; Cells[3,1]:=SMT_Table.FieldbyName('datum_aend').asstring; StrGr_Aenderung.Options:= [goFixedHorzLine, goFixedVertLine, goHorzLine, goVertLine]; end; Form1.Update; Form1.ShowModal; finally StrGr_Aenderung.Free; // fehlte ganz SMT_Table.Free; SoapManager.Free; Form1.Free; end; end; exports benutzerdetails_anzeigen; Hope it helps onlinekater |
Re: DLL Einbindung - Fehler beim Beenden
situation unverändert...trotzdem super das du dir Zeit nimmst....
|
Re: DLL Einbindung - Fehler beim Beenden
Forms in DLLs geht ueblicherweise schief.
|
Re: DLL Einbindung - Fehler beim Beenden
jetzt bleibt Dir eigentlich nur noch, auszuprobieren, welche der verwendeten Komponenten den Fehler verursacht.
Einfach eine nach der anderen auskommentieren und gucken, wann der Fehler sich verdünnisiert. @Robert Marquardt: Habe eigentlich noch keine Probleme mit Forms in DLLs gehabt. Gruß onlinekater |
Re: DLL Einbindung - Fehler beim Beenden
habe die Komponenten nach und nach entfernt, es tut sich nichts, falls ich eine Lösung finde werde ich sie selbstverständlich posten...
|
Re: DLL Einbindung - Fehler beim Beenden
Zeig mal den Code, mit dem du die Funktion aufrufst.
Evtl. hast du da einen Fehler gemacht (z.B. fehlendes stdcall). :) |
Re: DLL Einbindung - Fehler beim Beenden
Morgen poste ich den anderen Code. ich benutze allerdings stdcall, wie oben bereits zu sehen:
procedure benutzer(Provider,feld,eintrag,einrag_detail:strin g)stdcall; external 'Aenderungsinfo.dll'; Mir ist nochwas eingefallen: Ich benutze in der Funktion mit dem Aufruf einmal getmem, welchen ich am Ende allerdings wieder freigebe... mfg |
Re: DLL Einbindung - Fehler beim Beenden
Zitat:
|
Re: DLL Einbindung - Fehler beim Beenden
Zitat:
Natürlich sind auch alle globalen Variablen der VCL doppelt im Speicher. Application aus der DLL ist nicht Application aus der Anwendung. Für sowas gibt nimmt man Packages statt DLLs und Ruhe ist. Möglich wäre es vllt auch in DLL und Exe die RTL & VCL als Runtime package anzugeben, aber da kommt wahrscheinlich immer noch Käse raus. (Habe ich noch nicht probiert) |
Re: DLL Einbindung - Fehler beim Beenden
Hm,
wir haben aber in unserem aktuellen Projekt Forms in dlls gepackt und die werden dynamisch aufgerufen und alles laeuft (seltsamerweise???) perfekt! |
Re: DLL Einbindung - Fehler beim Beenden
Zitat:
Solange die Forms nix mit der VCL der App zu tun haben und/oder mit der gleichen Delphi version gegen die gleichen VCL/RTL DCUs kompostiert wurden, kann ich mir gut vorstellen, dass es passt. (noch...) Aber IMHO ist auch das Käse. Es macht einfach keinen (nada, niente, nüschts) Sinn, sich mit DLLs zu ärgern und Code zu duplizieren, wenn man nur Delphi mit Delphi reden lassen will. |
Re: DLL Einbindung - Fehler beim Beenden
Ja aber gibst du packages raus kann jeder das Ding schneller ansehen als du Hup sagen kannst!
Und ausserdem wollen wir halt eben verschiedene Versionen rausbringen und was nicht in der Exe steht ist nicht crackbar. Aber darueber haben sich schon viele gestritten! |
Re: DLL Einbindung - Fehler beim Beenden
Zitat:
Jetzt weiß ich auch, warum ich hier von Anfang an nicht antworten wollte und klinke mich vorsichtshalber gleich aus dem Thread raus. :hi: |
Re: DLL Einbindung - Fehler beim Beenden
Und warum so provokant nun?
Sagte ich irgendwas mit dlls sind uncrackbar? NEIN! Ich sagte dass was nicht in der dll ist kann man auch nicht freischalten und somit ne Vollwertige Version erhalten. Richtig? Nicht mehr, nicht weniger! Danke fuers Gespraech! |
Re: DLL Einbindung - Fehler beim Beenden
Ich bin gestern per Zufall auf die Lösung meines Problems gekommen. Bei einer Kollegin kam folgende Fehlermeldung: Anwendung konnte nicht gestartet werden, weil qtintf.dd nicht gewfunden wurde.. usw
In einem anderen Beitrag habe ich dann den Hinweis auf CLX Units gefunden... Unbewusst hatte ich in die DLL eine dieser Q-Units eingebunden, nachdem ich diese entfernt hatte ging es...
Delphi-Quellcode:
Vielen Dank für eure Hilfe!
uses
ShareMem, SysUtils, Dialogs, StdCtrls, Forms, Classes, Grids, kbmMemTable, uSOAPClient, QGraphics, //<--- Diese Unit erzeugt den Fehler... Controls; mfg fsc |
Re: DLL Einbindung - Fehler beim Beenden
Moin Zusammen,
nur um noch mal etwas zum Runtime-Error 216 (sporadisch 217) hinzuzufügen: Bei mir tritt das Ganze in einem D7-Projekt auf, nachdem ich in einer eingebundenen Unit eine Kleinigkeit geändert habe (es wurden ein paar Zeilen auskommentiert). Es wird keine DLL eingebunden (ausser denen die implizit dazugehören versteht sich). Diese Unit wird identisch in einem D2006-Projekt benutzt, und in diesem Falle tritt das Problem nicht auf (es werden auch die gleichen Funktionen benutzt). Der Fehler tritt immer nach dem finalization-Abschnitt auf. Starte ich das Programm aus der IDE heraus, und beende es, so erhalte ich einen "Zugriff verweigert". |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz