SIGSEGV - Gründe / Auslöser finden...

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Latze
Beiträge: 60
Registriert: Sa 4. Jul 2009, 09:11
OS, Lazarus, FPC: Win7 / Linux (Lazarus 1.4.0)
CPU-Target: 32Bit/64Bit

SIGSEGV - Gründe / Auslöser finden...

Beitrag von Latze »

Ich hab nun schon einige male gelesen, dass SIGSEGV unterschiedliche Gründe haben kann. Ich habe ein kleines Programm geschrieben, dass Datensätze aus einer Datenbank kontrolliert, auswertet und ein entsprechendes Ergebnis druckt. Nun steh ich vor dem Problem, dass ich bei einem Datensatz zwar eine vollständige und auch korrekte Auswertung drucken kann, aber einen SIGSEGV bekomme, wenn ich das Programm beende. Der Ausdruck passt schon mal. Der Datensatz macht auch einen korrekten Eindruck, jedenfalls meckert die Software, mit der er erstellt wurde nicht. Bei anderen Datensätzen kann ich das Programm ohne Fehler beenden.

Die fertige exe macht mit dem einen Datensatz auch keine Probleme, evtl. ein Bug in Lazarus?

Meine Frage dazu ist etwas allgemeiner: Gibt es eine Möglichkeit, einem SIGSEGV auf den Grund zu gehen? Den einzigen Anhaltspunkt gibt ja das Assemblerfenster aber meine Kenntnisse in Assembler beschränken sich auf Microcontroller und dabei wollte ich es eigentlich auch belassen.

Gruß
Latze
Wer glaubt, etwas zu sein, hat aufgehört, etwas zu werden.

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: SIGSEGV - Gründe / Auslöser finden...

Beitrag von mse »

Der erste Schritt ist, das Projekt mit -gh zu kompilieren. Dadurch wird der heaptrace memory manager verwendet, welcher bei der Speicherverwaltung viele Tests durchführt und möglicherweise näher bei der Ursache Alarm schlägt.
Wie sieht denn der Aufrufstack beim Absturz aus? Möglicherweise müssen die FPC Bibliotheken mit debuginfo kompiliert werden um ausagekräftige Informationen zu erhalten.
In verzweifelten Fällen hilft auch die Verwendung von Valgrind, Valgrind hat mir schon mehrmals das Leben gerettet...

Martin

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: SIGSEGV - Gründe / Auslöser finden...

Beitrag von Euklid »

Latze hat geschrieben:Meine Frage dazu ist etwas allgemeiner: Gibt es eine Möglichkeit, einem SIGSEGV auf den Grund zu gehen? Den einzigen Anhaltspunkt gibt ja das Assemblerfenster aber meine Kenntnisse in Assembler beschränken sich auf Microcontroller und dabei wollte ich es eigentlich auch belassen.

Gruß
Latze


Hallo Latze,

SEGV steht für Segment Violation - d.h. es handelt sich bei dem Fehler um eine Speicherzugriffsverletzung. Diese sollten, auch wenn sich die Auswirkung in der fertigen EXE nicht direkt zeigen, behoben werden, da ansonsten Sicherheitslücken, Speicherleichen u.ä. entstehen.

Es gibt eine sehr effektive Methode, den SIGSEVs auf den Grund zu gehen - welche von mse schon angerissen wurden. Hier eine Anleitung:

1. Im Menü Projekt-->Compilereinstellungen-->Linken bei "Heaptrc-Unit verwenden" ein Häckchen machen.
2. Start-->Alles kompilieren
3. Das fertig kompilierte Programm von der Konsole aus öffnen.
4. Die Aktion ausführen, die zur SIGSEV geführt hat. Dann das Programm beenden.

Anschließend bekommst du in die Konsole die Unit sowie die Zeile der Unit genannt, in der der Fehler verursacht worden ist. Zudem erhältst du einen Aufrufstack, der den "Weg" des Fehlers nachvollziehen lässt. Wenn du Fragen zur Ausgabe der Heaptrc-Unit hast, kannst du die Ausgabe auch einfach hier posten. Der ein oder andere hier im Forum wird dir dann weiterhelfen können.

Viele Grüße, Euklid

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: SIGSEGV - Gründe / Auslöser finden...

Beitrag von Scotty »

Vielleicht eine Idee: Ich habe in meinem Programm dynamisch ein Formular erzeugt, dieses ggf. per Free gelöscht und beim Beenden mit if assigned() geprüft ob es noch da ist und dann ein Free hinterher geschoben. Dummerweise führte das erste Free nicht zu einem Nil-Zeiger und hat beim zweiten Free eine SIGSEV ausgelöst. (FreeAndNil hilft da manchmal, geht aber nicht immer.) Warum das so ist, war mir schon mit Delphi nicht klar. :roll:

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: SIGSEGV - Gründe / Auslöser finden...

Beitrag von Hitman »

.Free löst einfach nur das "Destroy" aus, verändert aber logischer weise nicht die Variable, von der aus du das aufrufst ... darum gibt es ja FreeAndNil, damit die Variable auch auf Nil gesetzt wirst - anders kannst du später nicht feststellen, ob das Objekt nun schon freigegeben wurde oder nicht.

martin_frb
Beiträge: 573
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: SIGSEGV - Gründe / Auslöser finden...

Beitrag von martin_frb »

Scotty hat geschrieben:Vielleicht eine Idee: Ich habe in meinem Programm dynamisch ein Formular erzeugt, dieses ggf. per Free gelöscht und beim Beenden mit if assigned() geprüft ob es noch da ist und dann ein Free hinterher geschoben. Dummerweise führte das erste Free nicht zu einem Nil-Zeiger und hat beim zweiten Free eine SIGSEV ausgelöst. (FreeAndNil hilft da manchmal, geht aber nicht immer.) Warum das so ist, war mir schon mit Delphi nicht klar. :roll:


Objekte sind in Wirklichkeit Pointer: das heist.
var
Form1: TForm;
reserviert 4 bytes (8 bei 64 bit Architektur)

Form1 := TForm.Create(xxx);
reserviert den speicher der die aktuellen Daten der Form enthält.

SomeVar := Form1;
kopiert den Pointer, aber nicht die Daten.

Form1.Free;
gibt den speicher der von Create reserviert wurde frei.
Aber From1 und SomeVar, behalten ihren wert (nur das der Zeiger jetzt auf einen speicher block zeigt der nicht mehr reserviert, also ungültig ist.

FreeAndNil(Form1)
ist das selbe wie:
if Form1<> nil then Form1.Free;
Form1 := nil
Das heißt selbst dann, hat SomeVar, noch den alten Zeiger

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: SIGSEGV - Gründe / Auslöser finden...

Beitrag von Scotty »

Mein fehlendes Verständnis bezieht sich eher darauf, warum Free nicht immer im Sinne von FreeAndNil ausgeführt wird. Mit dem kaputten Zeiger kann keiner mehr was anfangen. Aber das ist nun auch etwas OT und hilft wohl beim Debuggen wenig.

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: SIGSEGV - Gründe / Auslöser finden...

Beitrag von mse »

Scotty hat geschrieben:Mein fehlendes Verständnis bezieht sich eher darauf, warum Free nicht immer im Sinne von FreeAndNil ausgeführt wird.


Freeandnil hat einen var parameter für den Instanzpointer, die Adresse der Instanzvariable muss bekannt sein. Dies ist innerhalb der Methoden der Klasse meist nicht der Fall, zudem können, wie martin_frb bereits geschrieben hat, mehre Variablen einen pointer auf die Instanz halten, hier versagt freeandnil sowieso.

Martin

Latze
Beiträge: 60
Registriert: Sa 4. Jul 2009, 09:11
OS, Lazarus, FPC: Win7 / Linux (Lazarus 1.4.0)
CPU-Target: 32Bit/64Bit

Re: SIGSEGV - Gründe / Auslöser finden...

Beitrag von Latze »

Danke, heaptrace hat mir gefehlt. Jetzt werd ich mal versuchen, das alles auseinander zu wuseln.
Wer glaubt, etwas zu sein, hat aufgehört, etwas zu werden.

Antworten