![]() |
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
|
AW: Bekomme einen Error (sporadisch)
Nja, erstmal wäre es praktisch, wenn du in deinem DP-Profil deine Delphiversion angibst oder diese in den Threads mit nennst, damit man geziehlt auf Besonderheiten dieser Version eingehen kann.
Aber so für den Anfang: - Strg+Alt+W (oder irgendwo im Menü "Ansicht" den Punkt "Überwachte Ausdrücke") > dort kann man Variablennamen angeben, deren Werte angezeigt werden sollen, wenn sich das Programm im Pause-Modus befindet (im Debugger angehalten) - oder, ebenfalls wenn der Debugger das Programm angehalten hat, dann einfach mal den Mauszeiger für ein paar Sekunden über einen Variablennamen im Quellcode drüberhalten angehalten ist z.B. das Programm, nachdem eine Exception ausgelöst wurde oder wenn das Programm in einen Haltepunkt (F5) reingelaufen ist Ansonsten kann man das Menü "Start" und die Abteilung "Debug-Fenster" im Menü "Ansicht" empfehlen. |
AW: Bekomme einen Error (sporadisch)
supi, euch allen vielen dank! ich hab den fehler gefunden.
Delphi-Quellcode:
EDIT: Sorry himitsu, werd ich gleich abändern. Ich arbeite mit dem alten rustikalen Delphi 7 *gg* Und danke für deine Tips!
if Makro = nil then
begin new (Makro); Makro.Next := nil; RefMakro := Makro; new (RefMakro.Commands); Makro.TimeStamp := TimeStamp; RefCommand := Makro.Commands; RefCommand.Next := nil; //<--- Diese Zeile hier hat gefehlt, dadurch hat assigned wohl true geliefert... Makro.Commands.InputName := Name; Makro.Commands.Pressed := Pressed; end |
AW: Bekomme einen Error (sporadisch)
Aber auch der Code von dem "rustikalen" Delphi verdient es richtig gehighlightet zu werden. Verwende bitte für Delphi-Code den Delphi-Tag!
|
AW: Bekomme einen Error (sporadisch)
Und bitte gib deinem Beitrag einen aussagekräftigen Titel.
|
AW: Bekomme einen Error (sporadisch)
Zitat:
|
AW: Bekomme einen Error (sporadisch)
Du kannst deine Beiträge und deren Titel innerhalb von 24 Stunden noch editieren. Es muss also gehen. Klick mal auf die Schaltfläche "Erweitert".
|
AW: Bekomme einen Error (sporadisch)
Und danach kannst du den Beitrag mit der Bitte der Änderung melden. Einer vom Team wird deinem Wunsch dann nachkommen.
|
AW: Access Violation mit einfach verketteter Liste
Danke ;) nun sollte alles passen!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:11 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