AGB  ·  Datenschutz  ·  Impressum  







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

EAccessViolence bei Linearer Liste

Ein Thema von Riclem · begonnen am 6. Mär 2016 · letzter Beitrag vom 6. Mär 2016
Antwort Antwort
Riclem

Registriert seit: 16. Mai 2014
8 Beiträge
 
#1

EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 12:39
Delphi-Version: 2005
Hey,

ich arbeite zur Zeit an einem Schulprojekt und komme bei einem Fehler einfach nicht weiter.
Ich habe eine FirstIn-FirstOut-Liste, bei der Elemente hinzugefügt und gelöscht werden. Für Hilfe bin ich wirklich dankbar.
Listendefinition:
Delphi-Quellcode:
type
  Zeiger = ^elementtyp;

  elementtyp = record
    Zeit_Kunde_an: integer;
    Zeit_Kunde_noetig: integer;
    ref: Zeiger;
  end;
Hinzufügen von Elementen
Delphi-Quellcode:
procedure FiFo(Anker: Zeiger);
var p, q: Zeiger;
  stop: integer;
begin
  stop := GetTickCount;
  while ((GetTickCount) < (stop + 1600)) and (Form1.Aufhoeren.checked=false) do
  begin
    new(q);
    q^.ref := nil;
    q^.Zeit_Kunde_an := GetTickCount;
    q^.Zeit_Kunde_noetig := 1000;
    if Anker = nil then
      Anker := q
    else
      p^.ref := q; //Hier war früher eine EAccessViolation - auf wundersame Weise verschwunden
    p := q;
    Form1.K1_Z.caption := IntToStr(StrToInt(Form1.K1_Z.caption) + 1);
    Pausieren(400);
  end;
end;
Löschen von Elementen
Delphi-Quellcode:
procedure Bearbeitung();
var K_Z_noetig: integer;
  p: Zeiger;
begin
  while Form1.Aufhoeren.checked = false do
  begin
    if (StrToINt(Form1.K1_Z.Caption) > 0) and (Form1.Aufhoeren.checked = false) then
    begin
      K_Z_noetig := K1_A^.Zeit_Kunde_noetig;
      Pausieren(K_Z_noetig);
      p := K1_A;
      K1_A := K1_A^.ref; //HIER tritt sie jetzt auf
      dispose(p);
      Form1.K1_Z.caption := IntToStr(StrToInt(Form1.K1_Z.caption) - 1);
    end
    else Pausieren(400);
  end;
end;
Viele Grüße und danke schonmal
Riclem
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#2

AW: EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 12:56
Das Anker Argument muss schonmal als var Anker: Zeiger deklariert werden, damit die Zuweisung Anker := q durchgeführt werden kann. Die markierte Zeile knallt deshalb, weil zu diesem Zeitpunkt p noch nicht initialisiert ist. p^.ref geht deshalb ins Leere. Es war vermutlich Anker^.ref := q gewollt.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl ( 6. Mär 2016 um 13:00 Uhr)
  Mit Zitat antworten Zitat
Riclem

Registriert seit: 16. Mai 2014
8 Beiträge
 
#3

AW: EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 13:30
Ah klar stimmt, das VAR muss da natürlich hin. Zur Initialisierung von p: Da p^.ref := q; im else-Zweig steht, wird es erst beim zweiten Durchgang ausgeführt. Dann ist es doch über p:=q; schon initialisiert?
Hast du vielleicht für die zweite markierte Zeile noch eine Idee?

Vielen Dank bisher!!
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#4

AW: EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 14:09
Zur Initialisierung von p: Da p^.ref := q; im else-Zweig steht, wird es erst beim zweiten Durchgang ausgeführt. Dann ist es doch über p:=q; schon initialisiert?
Das ist natürlich korrekt .. zumindest wenn du implizierst, dass Anker initial immer nil ist. Dein Funktionsdesign (insbesondere die Logik deiner Funktionskapselung) ist leicht unintuitiv

An der zweiten Stelle wird K1_A zu irgendeinem Zeitpunkt wohl nil sein. Warum, weshalb, sehe ich grade im Gewurschtel der globalen Variablen und missbrauchten GUI Controls leider nicht.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Riclem

Registriert seit: 16. Mai 2014
8 Beiträge
 
#5

AW: EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 14:18
Haha, ja so kann man das wohl nennen Dann werde ich das wohl selber suchen müssen. Sag mal, was bedeutet denn so eine EAccessViolation eigentlich so? Bei mir trat sie auf beim:
- Auslesen eines Elements der Liste
- bei Anweisungen à la x:=y^.ref
Gibt es da irgendwie bestimmte Ursachen oder so?
Vielen Dank
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#6

AW: EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 14:37
Eine Access Violation tritt immer dann auf, wenn du versuchst auf einen ungültigen Speicherbereich zuzugreifen (lesend oder schreiben). Ungültig ist ein Speicherbereich dann, wenn er vorher nicht allocated wurde.

Sowas passiert häuftig, wenn man beispielsweise mit Objekten arbeitet und vorher den Create Aufruf vergessen hat, oder wenn man Objekte bereits mit Free wieder zerstört hat, aber danach noch mit Ihnen arbeiten will. In deinem Falle ist die fehlerhafte Pointer-Arithmetik Schuld (präziser gesagt, wird dein Zeiger irgendwann entweder auf nil , oder eine andere nicht existente Speicherstelle zeigen. Sobald du dann mit ^ dereferenzierst, knallt es).

Generell ist es btw. immer eine gute Idee, Funktionalitäten in Klassen zu kapseln. Hier wäre auf die Schnelle mal eine an deine Delphi Version (keine Standard-Queue-Klasse, keine Generics) angepasste Implementierung einer FIFO-Liste (Queue):
Delphi-Quellcode:
type
  TQueueData = record
  public
    Foo: Integer;
    Bar: String;
  end;

  TQueue = class(TObject)
  strict private type
    PQueueItem = ^TQueueItem;
    TQueueItem = record
    public
      FLink: PQueueItem;
      BLink: PQueueItem;
      Data: TQueueData;
    end;
  strict private
    FFirst: PQueueItem;
    FLast: PQueueItem;
    FCount: Integer;
  public
    procedure Enqueue(const Data: TQueueData);
    function Dequeue: TQueueData;
    function Peek: TQueueData;
    procedure Clear;
  public
    destructor Destroy; override;
  public
    property Count: Integer read FCount;
  end;

{ TQueue }

procedure TQueue.Clear;
var
  Temp: PQueueItem;
begin
  while Assigned(FFirst) do
  begin
    Temp := FFirst^.FLink;
    Dispose(FFirst);
    FFirst := Temp;
  end;
  FLast := nil;
  FCount := 0;
end;

function TQueue.Dequeue: TQueueData;
var
  Temp: PQueueItem;
begin
  if (FCount = 0) then raise Exception.Create('No items in queue');
  Result := FFirst^.Data;
  Temp := FFirst^.FLink;
  Dispose(FFirst);
  if Assigned(Temp) then
  begin
    Temp^.BLink := nil;
    FFirst := Temp;
  end else
  begin
    FFirst := nil;
    FLast := nil;
  end;
  Dec(FCount);
end;

destructor TQueue.Destroy;
begin
  Clear;
  inherited;
end;

procedure TQueue.Enqueue(const Data: TQueueData);
var
  Item: PQueueItem;
begin
  New(Item);
  Item^.FLink := nil;
  Item^.BLink := FLast;
  Item^.Data := Data;
  if (not Assigned(FFirst)) then
  begin
    FFirst := Item;
  end;
  if Assigned(FLast) then
  begin
    FLast^.FLink := Item;
  end;
  FLast := Item;
  Inc(FCount);
end;

function TQueue.Peek: TQueueData;
begin
  if (FCount = 0) then raise Exception.Create('No items in queue');
  Result := FFirst^.Data;
end;
Auch ist es eigentlich immer schlecht, wenn man Business-Logik in die GUI reinwurschtelt. So ein Label als Counter zu verwenden, ist ein No-Go Dafür ist es einfach nicht gemacht, was man schon an deinem umständlichen StrToInt und IntToStr Gemenge sieht.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl ( 6. Mär 2016 um 15:16 Uhr)
  Mit Zitat antworten Zitat
Riclem

Registriert seit: 16. Mai 2014
8 Beiträge
 
#7

AW: EAccessViolence bei Linearer Liste

  Alt 6. Mär 2016, 14:57
Wow super, vielen Dank. Jetzt klappt es
Danke, schönen Sonntag noch!
  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 01:46 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