Zugriffsverletzung bei fpc_ansistr_decr_ref

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Warf
Beiträge: 2122
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Zugriffsverletzung bei fpc_ansistr_decr_ref

Beitrag von Warf »

Hey ho,
ich schreibe grade ein Programm welches aus einer Datei verschiedene Daten, Objektproperties ausliest. Das auslesen klappt soweit auch ganz gut, nur jetzt habe ich ein kleines Problem. Sobald das Programm aus der Lesemethode raus springt bekomme ich eine Zugriffsverletzung bei der funktion fpc_ansistr_decr_ref, also der Funktion um den Referenzzähler eines Strings zu reduzieren.

Ich bin komplett ratlos warum. Der Code, stark reduziert da es sich sonst um über 150 Zeile handeln würde:

Code: Alles auswählen

procedure TMoverProperties.Load(Prop, PropText: TBytes;
  DefO, DefN, DefA, DefI, DefS: TConstReader);
 
  function GetID(Key: string): longword;
  var
    tmp: string;
  begin
    TTextReader.SplitKey(Key, tmp, Result);
  end;
 
var
  script: TScriptReader;
  i: integer;
  proptxt: TTextReader;
  tmp: PMoverProperty;
var
  Tok: string;
begin
  FDefO := DefO;
  FDefN := DefN;
  FDefA := DefA;
  FDefI := DefI;
  FDefS := DefS;
  script := TScriptReader.Create(Prop);
  proptxt := TTextReader.Create(PropText);
  try
    while not (script.EndOfFile) do
    begin
      New(tmp);
      FillChar(tmp^, SizeOf(TMoverProperty), #00);
      script.ReadToken(tok);
      tmp^.ID := FDefO.GetConstByKey(Tok).uValue;
      script.ReadToken(tok);
      tmp^.Name := proptxt.KeyText[tok];
      tmp^.NameID := GetID(Tok);
      script.ReadToken(tok);
      tmp^.DefaultVal := FDefN.GetConstByKey(tok).uValue;
      tmp^.DS1 := script.GetInteger;
      tmp^.DS2 := script.GetInteger;
      tmp^.DS3 := script.GetInteger;
      tmp^.DA1 := script.GetInteger;
      tmp^.DA2 := script.GetInteger;
      tmp^.ER1 := script.GetInteger;
      tmp^.ER2 := script.GetInteger;
      // viele mehr solcher zeilen
      Props.Add(tmp);
    end;
  finally
    script.Free;
    proptxt.Free;
  end;
end;
Und der aufruf der Methode findet hier statt

Code: Alles auswählen

 
procedure TForm1.FormCreate(Sender: TObject);
procedure FillWithPrefix(sl: TStrings; c: TConstReader; pref: String);
var i: Integer;
begin
  sl.Add('-');
  for i:=0 to c.Count-1 do
    if AnsiStartsStr(pref, c.Constants[i].Key) then
      sl.Add(Format('%s - %d', [c.Constants[i].Key, c.Constants[i].uValue]));
end;
 
var defn, defo, defa, defi, defs, pm, ptxt: TBytes;
  fs: TFileStream;
  p: String;
begin
  // Dateien über FileStream in Arrays laden hab ich übersprungen
 
  FDefN:=TConstReader.Create;
  FDefI:=TConstReader.Create;
  FDefA:=TConstReader.Create;
  FDefO:=TConstReader.Create;
  FDefS:=TConstReader.Create;
  FDefN.Read(defn, '');
  FDefA.Read(defa, '');
  FDefI.Read(defi, '');
  FDefO.Read(defo, '');
  FDefS.Read(DefS, '');
 
  Movers:=TMoverProperties.Create;
  Movers.Load(pm, ptxt, DefObj, DefNeuz, DefAttr, DefItem,DefSound);
 ...
Die Script.ReadToken und GetInteger Methode:

Code: Alles auswählen

 
procedure TScriptReader.ReadToken(out tok: string);
begin
  tok := '';
  repeat
    tok := tok + FLine[FPosition];
    Inc(FPosition);
  until (FPosition > Length(FLine)) or (FLine[FPosition] in [' ', #9]);
  ReadToNext;
end;    
 
procedure TScriptReader.ReadInteger(out i: integer);
var
  s: string;
begin
  ReadToken(s);
  if s[Length(s)] = ',' then
    s := Copy(s, 1, Length(s) - 1);
  if AnsiStartsText('0x', s) then
  begin
    i := Hex2Dec(Copy(s, 3, Length(s) - 2));
  end
  else if s = '=' then
    i := -1
  else if s = 'FALSE' then
    i := 0
  else if s = 'TRUE' then
    i := 1
  else
    i := StrToInt(s);
end;
Ich habe schon versucht alle String Variablen aus der Load Methode zu entfernen und konstante werte anzugeben, immer noch das selbe Problem. Ich habe mal das Script.Free und proptxt.Free auskommentiert um zu sehen ob der Fehler irgendwo dort liegt, auch Fehlanzeige.

An der TScriptReader Klasse kann es eigentlich nicht liegen, die funktioniert bei allen anderen Projekten problemlos.

Lazarus Trunc und fpc 3.0.0rc2 Windows 10 64 Bit, anwendung ist 32 Bit

PS: Ich weiß dass die ReadToken methode recht ineffizient ist, die quelltext datei ist etwas älter und ich kam noch nicht dazu sie zu verbessern
Dateianhänge
Fehler
Fehler

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Zugriffsverletzung bei fpc_ansistr_decr_ref

Beitrag von mse »

Warf hat geschrieben:

Code: Alles auswählen

 
      New(tmp);
...
 
      Props.Add(tmp);
 
Was ist "Props" und wo und wie wird "tmp" freigegeben?

Warf
Beiträge: 2122
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Zugriffsverletzung bei fpc_ansistr_decr_ref

Beitrag von Warf »

mse hat geschrieben:
Warf hat geschrieben:

Code: Alles auswählen

 
      New(tmp);
...
 
      Props.Add(tmp);
 
Was ist "Props" und wo und wie wird "tmp" freigegeben?
Props ist eine TList und die elemente werden bei dem Freigeben der liste wieder freigegeben:

Code: Alles auswählen

 
procedure TMoverProperties.Clear;
var
  i: integer;
begin
  for i := 0 to Props.Count - 1 do
    Dispose(PMoverProperty(Props[i]));
  Props.Clear;
end;
 
constructor TMoverProperties.Create;
begin
  Props := TList.Create;
end;
 
destructor TMoverProperties.Destroy;
begin
  Clear;
  Props.Free;
end;

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Zugriffsverletzung bei fpc_ansistr_decr_ref

Beitrag von mse »

Und macht dispose() auch finalize()? Vermutlich nicht, sonst wäre fillchar() bei new() auch nicht notwendig. Versuche doch mal versuchshalber

Code: Alles auswählen

 
 for i := 0 to Props.Count - 1 do begin
    finalize(PMoverProperty(Props[i]));
    Dispose(PMoverProperty(Props[i]));
 end;
 
oder schau mit dem debugger ob dispose() das schon erledigt.

Warf
Beiträge: 2122
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Zugriffsverletzung bei fpc_ansistr_decr_ref

Beitrag von Warf »

Hab das Problem gefunden, es lag wo ganz anders, in einer anderen datei hatte ich einem String außeversehen $FF zugewiesen, warum weiß ich selbst nicht, hab da anscheinden das mit irgend etwas vertauscht...

Danke Trozdem für die Mühe

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Zugriffsverletzung bei fpc_ansistr_decr_ref

Beitrag von mse »

Ich habe nachgeschaut, new() ruft fpc_initialize() auf, dispose ruft fpc_finalize() auf, siehe Anhang. Du könntest also auch auf fillchar() nach new() verzichten wenn alle Felder gesetzt werden.
Dateianhänge
dispose.png

Antworten