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.