![]() |
Access Violation mit einfach verketteter Liste
Moin,
ich habe folgende Struktur meiner Daten:
Delphi-Quellcode:
Im Prinzip soll das einfach eine Einfach verktettete Liste sein (PMakroList), die eine Reihe von Commands enthält (PCommandList), auch als einfach verkettete Liste.
PCommandList = ^TCommandList;
TCommandList = record InputName : Integer; Pressed : Boolean; Next : PCommandList; end; PMakroList = ^TMakroList; TMakroList = record TimeStamp : Integer; Commands : PCommandList; Next : PMakroList; end; Das Anlegen der Liste funktioniert einwandfrei und ich habe auch eine Routine in meinem Objekt, das die Struktur speichern soll. Dazu habe ich folgenden Code:
Delphi-Quellcode:
(über den stil sowas zu speichern lässt sich streiten, daher bitte keine große diskussion drüber).
procedure TMakro.SaveToFile(FileName : String);
var MRef : PMakroList; CRef : PCommandList; SaveFile : TextFile; I : Integer; begin AssignFile (SaveFile, FileName); ReWrite (SaveFile); WriteLn (SaveFile, 'ÿNAME' + MakroName); WriteLn (SaveFile, 'ÿBEGINDESCRIPTION'); for I := 0 to Description.Count - 1 do writeln (SaveFile, Description[I]); WriteLn (SaveFile, 'ÿENDDESCRIPTION'); WriteLn (SaveFile, 'ÿBEGINMAKRO'); MRef := Makro; while Assigned (MRef) do begin WriteLn (SaveFile, 'T' + IntToStr (MRef.TimeStamp)); CRef := MRef.Commands; while Assigned (CRef) do begin writeln (SaveFile, IntToStr (CRef.InputName) + '|' + BoolToStr (CRef.Pressed, True)); CRef := CRef.Next; end; MRef := MRef.Next; end; writeln (SaveFile, 'ÿENDMAKRO'); CloseFile (SaveFile); end; Wie man sieht wird einfach eine Textdatei hergenommen, erst diverse Optionen (name, beschreibung) von dem Objekt gespeichert und dann gehts an die List. Eigentlich dachte ich, dass ich genug kontrollabfragen drin hab, sodass ich nie ins leere laufen kann. Es sei noch gesagt, das alle leeren pointer mit "nil" initialisiert werden beim anlegen, damits bei assigned auch keine probleme gibt. Nun tritt sporadisch (immer mal wieder) an folgender Stelle ein fehler auf:
Delphi-Quellcode:
Und zwar ist der fehler eine Access violation. Ich gehe davon aus, das er auf MRef nicht zugreiffen kann. aber wo ist da mein fehler, bzw wo fehlt die kontrolle?
WriteLn (SaveFile, 'T' + IntToStr (MRef.TimeStamp))
Danke für die Hilfe Hybrid |
AW: Bekomme einen Error (sporadisch)
Überprüfe doch ob der Zeiger <> Nil is (Assigned())
|
AW: Bekomme einen Error (sporadisch)
Sollte doch eigentlich
Code:
tun, oder?
while Assigned (MRef) do
|
AW: Bekomme einen Error (sporadisch)
Abgesehn von der fehlenden Fehlerbehandlung für SaveFile,
welches aber mit diesem Problem nichts zu tun hat, dürfte dieser Code OK sein, also vermute ich eher einen Fehler beim Erstellen dieser Listen. Und ja, bei Pointern entpicht
Delphi-Quellcode:
einem
Assigned(P)
Delphi-Quellcode:
.
P <> nil
|
AW: Bekomme einen Error (sporadisch)
Eher
Delphi-Quellcode:
oder
if Assigned( MRef) then ...
Delphi-Quellcode:
if not Assigned( MRef) then Exit;
|
AW: Bekomme einen Error (sporadisch)
Hier ist der Code zum einfügen in die liste. Das ist der einzige Codeteil, der änderungen an der liste vornimmt:
Delphi-Quellcode:
Zu sagen: Die Variablen Makro und TimeStamp existieren als private in der Klasse TMakro. TimeStamp ist ein Integer und Makro ist PMakroList. RefCommand und RefMakro existieren ebenfalls als private.
procedure TMakro.AddInput (Pressed : Boolean; Name : Integer);
begin //Liste komplett leer if Makro = nil then begin new (Makro); Makro.Next := nil; RefMakro := Makro; new (RefMakro.Commands); Makro.TimeStamp := TimeStamp; RefCommand := Makro.Commands; Makro.Commands.InputName := Name; Makro.Commands.Pressed := Pressed; end else // TimeStamp existiert schon, also nur command in command liste einfügen begin if TimeStamp = RefMakro.TimeStamp then begin new (RefCommand.Next); RefCommand := RefCommand.Next; RefCommand.Next := nil; RefCommand.InputName := Name; RefCommand.Pressed := Pressed; end else // Timestamp größer als momentaner Referenztimestamp, also neuer Makro-Listen-Eintrag + neuen command einfügen begin new (RefMakro.Next); RefMakro := RefMakro.Next; RefMakro.Next := nil; RefMakro.TimeStamp := TimeStamp; new (RefMakro.Commands); RefCommand := RefMakro.Commands; RefCommand.Next := nil; RefCommand.InputName := Name; RefCommand.Pressed := Pressed; end; end; end; |
AW: Bekomme einen Error (sporadisch)
hmmmm, also wenn es wieder mal zu dieser Exception kommt, dann schau dir doch einfach im Debugger die Listen an.
Und vorallem die Stelle, an welcher dieses Problem auftreten tut. |
AW: Bekomme einen Error (sporadisch)
Da er aber schon prüft, ob das Object assigned ist, vermute ich, dass sich da ein Zeiger einschleicht, der zwar noch auch einer ehemaligen Struktur steht, diese Struktur ist aber schon wieder freigegeben. Der Zeiger wird dadurch ja nicht automatisch auf nil gesetzt.
Kapsel doch mal die Zugriffe mit try ... except und schau nach, bei welchem Object er diese Zicken macht und ob du evtl. da vorher was gelöscht hast. Was auch gerne passiert: Ein Object wird doppelt in eine Liste eingetragen. Dann einmal Free und aus der Liste gelöscht und fertig ist der Zugriffsfehler bei dem immer noch existierenden Eintrag in der Liste.
Delphi-Quellcode:
var
objlst : TObjectList; obj : TObject; begin objlst := TObjectList.Create; try obj := TObject.Create; objlst.Add( obj ); objlst.Add( obj ); objlst.Delete( 0 ); finally end; end; |
AW: Bekomme einen Error (sporadisch)
peinliche frage: ich hab noch nie mit nem debugger geschafft. was nimmt man da und wie schau ich mir die listen an?
Danke! |
AW: Bekomme einen Error (sporadisch)
Einfach Breakpoint an der Stelle setzen (oder kurz vorher) dann hält der Debugger hier an. Dann kannst du die Variablen durch Hinzufügen als überwachte Ausdrücke oder durch Überfahren mit der Maus auswerten
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:08 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