AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Problem TStringlist.free

Ein Thema von Master of the Wind · begonnen am 26. Dez 2005 · letzter Beitrag vom 26. Dez 2005
Antwort Antwort
Master of the Wind

Registriert seit: 20. Dez 2005
26 Beiträge
 
#1

Problem TStringlist.free

  Alt 26. Dez 2005, 09:44
Hallo,

ich muss leider nochmals mit der bitte an euch herantreten mir zu helfen. Ich habe ein Programm geschrieben, und wenn ich es beende kommt die Fehlermeldung ungültige Zeigeroperation. Der Compiler ist richtig eingestellt(Bereichsprüfung...). Der Fehler kommt genau an der markierten Stelle (Msglist.free, in dem destructor von TKonsole). Die Funktion Freeandnil hilft auch nix. Bitte schaut euch mal den Code an und helft mir bitte.



Ich bin über jede Antwort glücklich...Danke
Angehängte Dateien
Dateityp: rar engine_602.rar (800,1 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#2

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 10:00
Hallo,

zwei Sachen vorneweg:

Erstens: Häng bitte Deinen Quellcode als Archiv an, so ist das etwas lang und zum Testen fehlt Dein Form.
Zweitens: Mir ist aufgefallen, dass Du einen Pointer auf eine Klasse übergibst (PKernel). Eine Klasse ist aber schon ein Pointer, das kannst Du Dir also sparen.

Ansonsten sehe ich beim Überfliegen gerade keinen Fehler, ich kann das Programm aber so nicht ausprobieren (siehe Erstens).

Gruß
xaromz
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#3

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 10:24
Mir ist noch folgendes aufgefallen:

Delphi-Quellcode:
procedure TKernel.freeFunktionskette(address:PFunktionsglied);
begin
  if assigned(address) then
  begin
    if not (address^.danach=nil) then Funktionsketteabarbeiten(address^.danach);
    dispose(address);
  end;
end;
Solltest du nicht in dieser Funktion nicht freeFunktionskette(address^.danach); anstatt Funktionsketteabarbeiten(address^.danach); aufrufen?

Der Fehler tritt zwar bei der Freigabe der msglist auf, aber der Fehler kann durch anderen Code ausgelöst werden, der den Speicher von der msgList zerschiesst. Daher auch sowas wie hier aufgezeigt beachten und nachschauen. Ansonsten empfehle ich dir mal fastmm4 einzubinden und mal nachzuschauen, ob er dir nicht schon vorher Fehler meldet.
  Mit Zitat antworten Zitat
Master of the Wind

Registriert seit: 20. Dez 2005
26 Beiträge
 
#4

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 10:34
danke...ein Fehler weniger, aber leider nicht der den ich meine, der Fehler ist immernoch da mit der Msglist...
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#5

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 10:34
Hallo,

ich hab mir mal selbst ein Form gebastelt (ist ja nichts weiter drauf), jetzt fehlen mir zum Testen noch ein paar Textdateien. Die hab ich einfach mal ignoriert und beim Beenden des Programms Beenden() aufgerufen; bei mir kommt da kein Fehler.

Eine Anmerkung hab ich noch: Du deklarierst alles Mögliche in einer Unit und verwendest diese sowohl in Deinem Hauptprogramm als auch in einer DLL. Insbesondere Dein Form solltest Du nicht in die DLL packen. Bau Dir eine weitere Klasse, die Du in Deinem Form erstellst und dann der DLL übergibst. Am Besten erstellst Du Dir ein Interface, das ist die sauberste Lösung. Im jetzigen Zustand kann man das nur als grausam bezeichnen .

Gruß
xaromz
  Mit Zitat antworten Zitat
Master of the Wind

Registriert seit: 20. Dez 2005
26 Beiträge
 
#6

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 10:38
Interface...hmm..damit kann ich leider nicht soviel anfangen, kannst du mir da eine Hilfe empfehlen...
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#7

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 16:12
Hallo,

ich kenne leider kein gutes Tutorial für Interfaces. Aber ich versuche mal eine kleine Erklärung:

Interfaces sind im Grunde abstrakte Klassen. Sie beschreiben einen definierten Funktionsumfang einer Klasse. Hier mal ein Beispiel:
Delphi-Quellcode:
type
  IMyInterface = interface(IInterface)
  ['{7D30C89B-C144-420B-8F2C-501FEE4D787B}']
    function GetName: String;
    procedure SetName(const Value: String);
    procedure PrintName;
    property Name: String read GetName write SetName;
Wichtig ist: Ein Interface definiert keine Variablen. Folglich müssen alle Variablen über Properties mittels Getter und Setter definiert werden (siehe Name). Zusätzlich sollte ein Interface eine GUID haben, über die es eindeutig erkannt werden kann (['{...}']).

So wird ein Interface implementiert:
Delphi-Quellcode:
type
  TMyClass = class(TInterfacedObject, IMyInterface)
  private
    FName: String;
    function GetName: String;
    procedure SetName(const Value: String);
  public
    procedure MachWasAnderes;
    procedure PrintName;
    property Name: String read GetName write SetName;
  end;
Wichtig:
Alle Methoden, die im Interface definiert sind, müssen auch implementiert werden. Zusätzlich können noch beliebige weitere Methoden definiert werden.
Eine solche Klasse muss immer von TInterfacedObject abgeleitet werden, da dort einige Methoden definiert werden (z. B. Referenzählung, siehe unten).

Zur Benutzung:
Ein Interface besitzt einn Referenzzähler. Wenn dieser Null erreicht, zerstört sich das Objekt automatisch. Bei jeder Zuweisung einer Variablen wird der Referenzzähler automatisch erhöht. So weiß das Objekt, ob es noch benötigt wird. Dies hat einige Auswirkungen:
Interfaces sollten immer mit const übergeben werden:procedure TuWas(const Intf: IInterface); Interfaces sollten immer am Ende freigegeben werden, indem die Variable auf nil gesetzt wird:
Delphi-Quellcode:
procedure MachWas;
var
  Intf: IInterface;
begin
  Intf := CreateIrgendeinInterface;
  Intf.Blubber;
  intf := nil; <- Hier wird Intf freigegeben, da keine weitere Variable darauf zeigt
end;
Wenn ein Interface freigegeben wird, wird automatisch der Destructor des Objekts aufgerufen.

Da Interfaces sich selbst freigeben, sollte man immer darauf achten, am Ende des Programms sämtliche Referenzen zu entfernen, sonst erzeugt man ein Speicherleck.
Wenn eine Klasse, die ein Interface implementiert, einer Klassenreferenz zugewiesen wird, so wird der Referenzzähler nicht erhöht.

Nochmal mit obigem Beispiel zur Verdeutlichung:
Delphi-Quellcode:
procedure Eins;
var
  Obj: TMyClass;
  Intf: IMyInterface;
begin
  Obj := TMyClass.Create; // Referenzzähler = 0
  Obj.Name := 'Meier';
  Intf := Obj; // Referenzzähler = 1
  Intf.PrintName;
  Obj.MachWasAnderes;
  Intf := nil; // Referenzzähler = 0 -> Objekt wird zerstört
  Obj.Free; // Zugriffsfehler, Objekt ist schon zerstört
end;

procedure Zwei;
var
  Intf: IMyInterface;
begin
  Intf := TMyClass.Create; // Referenzzähler = 1;
  Intf.Name := 'Meier';
  Intf.PrintName;
  Intf.MachWasAnderes; <- Das geht nicht, MachWasAnderes ist in der Klasse definiert, nicht im interface
  Intf := nil; // Referenzzähler = 0 -> Objekt wird zerstört
end;
Anhand dieses Beispiels sieht man, dass man Objekte und ihre Interfaces nicht mischen sollte.
Eine Möglichkeit, dieses Konstrukt trotzdem zum Laufen zu bekommen wäre, den Referenzzähler manuell zu erhöhen:
Delphi-Quellcode:
procedure EinsA;
var
  Obj: TMyClass;
  Intf: IMyInterface;
begin
  Obj := TMyClass.Create; // Referenzzähler = 0
  Obj._AddRef; // Referenzzähler = 1
  Obj.Name := 'Meier';
  Intf := Obj; // Referenzzähler = 2
  Intf.PrintName;
  Obj.MachWasAnderes;
  Intf := nil; // Referenzzähler = 1
  Obj.Free; // Objekt wird zerstört
end;
Eine Sache noch:
Delphi-Quellcode:
procedure Drei;
var
  Intf1, Intf2: IMyInterface;
begin
  Intf1 := TMyClass.Create;
  Intf2 := Intf1;
  if (Intf1 = Intf2) then
    ShowMessage('Diese Meldung wird niemals erscheinen);
Intf2 := nil;
Intf1 := nil;
end;
Interfaces sind niemals identisch. ein Vergleich von Interfaces wird immer scheitern. Um dieses Problem zu beheben müsste jede erzeugte Klasse eine eindeutige ID erhalten, die über das Interface überprüft werden kann. Da verschiedene Interfaces das gleiche Objekt repräsentieren, wäre bei beiden Interfaces auch die ID gleich.

Was sind nun die Vorteile eines Interfaces?
Ein Interface ist sozusagen der Bauplan einer Klasse, den man benutzen kann, ohne die Klasse zu kennen. Das ist insbesondere bei DLLs interessant; eine DLL erzeugt ein Interface und das Hauptprogramm kann damit arbeiten, ohne dass der gesamte Klassen-Quellcode dem Hauptprogramm bekannt ist, da das Hauptprogramm das Interface kennt. Oder ein Hauptprogramm übergibt der DLL ein Interface, und die DLL kann damit arbeiten. Da die DLL nur das Interface kennt, bleibt diese schön klein.



Da ich heute etwas mit meinem neuen Delphi spielen wollte, habe ich mir erlaubt, Deinen Quellcode etwas zu überarbeiten.
Ich habe die einzelnen Klassen in eigene Units gesteckt und aus TKonsole ein Interface gebaut. Außerdem habe ich die Renderlogik aus dem Form genommen und in eine eigene Klasse (auch mit Interface) gesteckt. Programmlogik hat nämlich in einem Form nichts zu suchen, da gehört nur das Programminterface (Eingabe, Ausgabe) rein.
Da die beiden DLLs nur die Interfaces benötigen, sind sie viel kleiner geworden.
Schau Dir das Ganze mal an, vielleicht kanst Du damit ja was anfangen.

Ach ja, um die Anfangsfrage zu beantworten: Ein Fehler kommt bei mir nicht.

Gruß
xaromz
Angehängte Dateien
Dateityp: rar engine_112.rar (472,4 KB, 8x aufgerufen)
  Mit Zitat antworten Zitat
Master of the Wind

Registriert seit: 20. Dez 2005
26 Beiträge
 
#8

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 19:10
erstmal vielen vielen dank, klasse aber ein Problem hab ich gleich entdeckt. Die Tastureingabe wird nicht mehr angezeigt, weißt du gleich woran das liegt?
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#9

Re: Problem TStringlist.free

  Alt 26. Dez 2005, 23:01
Hallo,

ja, ich hab vergessen, den FormKeyDown-Event zuzuweisen. Einfach im Objektinspektor wieder zuweisen.

Gruß
xaromz
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:15 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