Warum bekomme ich hier ein SIGSEGV

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Benutzeravatar
photor
Beiträge: 512
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 3.2 (Gtk2) FPC 3.2.2
CPU-Target: 64Bit

Warum bekomme ich hier ein SIGSEGV

Beitrag von photor »

Hallo Forum,

vielleicht ist es einfach schon zu spät, aber ich verstehe nicht, warum es ein SIGSEGV gibt.

Kurze Erklärung: ich arbeite an einem Programm, dass eine Zeitreihe einliest und filtern soll. Der Code unten ist KEIN lauffähiges Programm sondern zunächst nur ein Code-Stück, dass hoffentlich genug Infos bietet (ich kann ein kleines Testprogramm nachliefern, wenn erforderlich). Aber zunächst will ich nur wissen, ob ich einen Knoten im Hirn habe.

Die Filter-Routine nimmt sich die Rohzeitreihe rawLTS und findet die Indizes der relativen Extreme, die in IdxList (einem dynamischen Integer-Array) gespeichert wird; das funktioniert auch soweit. Anschließend sollen jetzt die entsprechenden Datenpunkte in eine neue Zeitreihe kopiert werden. Dazu die for-Schleife über alle Einträge in IdxList (von 0 bis Length(IdxList) - 1), in der Speicher für einen Datenpunkt mit New allociert wird - darin soll der Punkt aus der Originalliste gespeichert werden, der an die DataList DL mit add angehängt wird (die wird dann zum Schluss nochmal in ein größeres Load-Time-Series-Objekt LTS gepackt).

Code: Alles auswählen

 type
  { DataPoint }
  TDataPoint = record
    Time : double;
    Value : double;
  end;
 
  { DataList }
  TDataList = Class(TList)
    DP : TDataPoint;
  end;                        
 
function filterLTS (rawLTS : TLTS) : TLTS;
var
  IdxList : Array of Integer;
  PtrDP : ^TDataPoint;
  DL : TDataList;
  i, idx : integer;
begin               
  // ... filter code fills IdxList with indices
  // array looks like this IdxList={0,2,4,5,8,10} 
  DL := TDataList.Create;
  for idx := 0 to Length(IdxList) - 1 do
  begin
    New(PtrDP);         // here SIGSEGV with idx=1 ????
    i := IdxList[idx];
    PtrDP := DataList[i];
    DL.Add(PtrDP);
  end;
end;
Das Problem: die for-Schleife wird mit dem ersten Punkt korrekt durchlaufen; die Zahlen für die Indizes und Feldlängen habe ich mit den Debugger geprüft. Beim nächsten Durchlauf (idx=1) wirft das Programm einen SIGSEGV (= Speicherzugriff-Fehler) beim New(PtrDP). Warum? (ein ähnliches Konstrukt gibt es schon im (hier nicht gezeigten) Code und funktioniert).

Ich nehme an, es ist was einfaches und ich seh' den Baum vor lauter Wald nicht. Dank für jeden Tipp,

Photor

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: Warum bekomme ich hier ein SIGSEGV

Beitrag von mse »

Vielleicht werden im ersten Durchgang Daten im Speichermanager überschrieben, was sich beim nächsten Aufruf von "new" auswirkt. Kompilieren mit -gh (Heaptrace) zeigt Speichefehler manchmal näher an der Stelle der Ursache. "PtrDP := DataList;" ist verdächtig, da wird der soeben mit "new" erhaltene pointer PtrDP überschrieben. Was ist "DataList"?

Benutzeravatar
photor
Beiträge: 512
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 3.2 (Gtk2) FPC 3.2.2
CPU-Target: 64Bit

Re: Warum bekomme ich hier ein SIGSEGV

Beitrag von photor »

Hallo mse,

Danke für den Hinweis auf die Compiler-Option. Die hat mir tatsächlich gezeigt, dass der Fehler (sehr simpel: Dispose auf eine Variable, die schon Disposed war - schähm! :oops: ) weiter oben (im Beispiel-Code hier nicht gezeigt) lag. Die Option bleibt also erstmal als Standard drin.

PtrPD soll den i-ten Punkt aus der DataList (besser den Pointer des Punktes) aufnehmen, so dass der in die neue Liste DL angehängt werden kann. Wahrscheinlich wird das noch vereinfacht - schließlich habe ich dort den Fehler vermutet und wollte sehen, wo es hängt.

Ciao,

Photor

Antworten