Ich habe mich extra hier angemeldet um den Grund für das fehlerhafte Verhalten meines Projekts zu erfahren. Mein Problem ist, dass eine als Parameter übergebene 2. Klasse, die dann in der 1. Klasse mit dem Typ IVorschauDatenbank gehalten wird, durch ein ".Free" der 1. Klasse beschädigt bzw. auch freigegeben wird.
Ich habe mir extra ein kleines Beispielprojekt gebaut, dass eigentlich genau das gleiche Verhalten aufweisen sollte, wenn es wirklich ein Problem von Free Pascal ist. Aber dort habe ich kein Problem damit. Daher würde ich gerne wissen, wie es dazu kommt, dass bei dem einen Projekt dieses Problem auftritt.
Lazarus: SVN-Revision: 37602
FPC: 2.6.0
Es handelt sich um einen Vokabeltrainer, der Daten in einer SQLite-Datenbank speichert und dafür eine passende Klasse "TVokabelDatenbank" hat, die neue Vokabeln in die DB schreibt, usw. . Ich habe eine Import-Funktion eingebaut, die aber auch eine Vorschau anbietet. Ich habe mir gedacht, dass es doch da mal sinnvoll wäre ein Interface zu verwenden: "IVokabelHinzufuegen". Ich habe also TVokabelDatenbank und TVorschauDatenbank, die so definiert sind:
Code: Alles auswählen
{ uVokabelDatenbank.pas }
IVokabelHinzufuegen = interface(IInterface)
procedure VokabelHinzufuegen(Vokabel: TVokabel);
end;
TVokabelDatenbank = class(TInterfacedObject, IVokabelHinzufuegen)
{...}
public
{...}
procedure VokabelHinzufuegen(Vokabel: TVokabel);
end;
{ uImportVorschau.pas }
TVorschauDatenbank = class(TInterfacedObject, IVokabelHinzufuegen)
{...}
public
{...}
procedure VokabelHinzufuegen(Vokabel: TVokabel);
{...}
end;
Die Klasse, die den Import erledigt sieht so aus:
Code: Alles auswählen
{ uImportExport.pas }
{TImporter}
TImporter = class
private
{...}
FDatenbank: IVokabelHinzufuegen;
{...}
public
{...}
constructor Create(AEinstellungen: TImportEinstellung; CSV: TCSVDocument;
Datenbank: IVokabelHinzufuegen);
end;
Nun kommt aber erst das Problem, das ich nicht verstehe:
Code: Alles auswählen
procedure TfrmImport.btnVorschauClick(Sender: TObject);
var
ImportEinstellung: TImportEinstellung;
Importer: TImporter;
begin
ImportEinstellung := ErstelleImportEinstellungen; // Ließt die Benutzereinstellungen ein
// Importer erstellen und Importieren
VorschauDatenbank.Leeren;
Importer := TImporter.Create(ImportEinstellung, CSV, VorschauDatenbank);
Importer.Importieren;
frmImportVorschau.ListeAktualisieren;
frmImportVorschau.ShowModal;
Importer.Free;
// ^ Hier wird die VorschauDatenbank gelöscht! DAS IST FALSCH!!!
// Deswegen gibt es nun diese Zeile: v
VorschauDatenbank := TVorschauDatenbank.Create;
end;
Ich könnte die VokabelDatenbank natürlich wie die VorschauDatenbank neu erstellen, aber das bekämpft nur die Symptome ohne das eigentliche Problem zu beseitigen. Auch könnte man die Vokabeln einer VorschauDatenbank auslesen und dann der VokabelDatenbank hinzufügen, aber warum nicht gleich die Vokabeln in die VokabelDatenbank eintragen, denn ein Umweg muss eigentlich nicht eingeschlagen werden.
Ich habe bisher im Internet auch nichts zu so einem Problem gefunden. Vielleicht liegt es daran, dass ich nicht wirklich weiß wonach ich suchen soll, aber dieser Fehler, wo auch immer er sein mag, ist wirklich ärgerlich.
"Gefixt" habe ich das Problem erstmal indem ich das Interface durch eine Klasse TVokabelHinzufuegen ersetze, die die procedure VokabelHinzufuegen als virtual und abstract definiert. Das geht zum Glück, weil die VokabelDatenbank von TObject erbt. Noch geht das, aber vielleicht muss ich später nochmal etwas ähnliches bauen, wo ich schließlich nicht um ein Interface herumkomme, wenn ich es einigermaßen schön lösen möchte.
Unter dem ersten Quelltextteil steht die Adresse zum kompletten Quellcode, vielleicht finden sich dort noch wichtige Hinweise.
Ich danke schon mal fürs Lesen und hoffe, dass zumindest einer von euch die Antwort auf das Problem kennt. Wenn noch Fragen da sind, beantworte ich sie gerne.

Vielen Dank,
Maximilian