2010-05-12 7 views
6

Plus, Das Programm läuft auf einem Arm-Gerät unter Linux, ich kann Stapelinformationen ausdrucken und Werte in dem zugewiesenen Sig-Seg-Handler registrieren. Das Problem ist, dass ich die Option -g nicht zur Quelldatei hinzufügen kann, da der Fehler möglicherweise aufgrund eines Downgrades der Leistung nicht reproduziert wird.Woher weiß ich, auf welche illegale Adresse das Programm zugreift, wenn ein Segmentierungsfehler auftritt?

+2

Zumindest mit GCC können Sie -g hinzufügen, ohne die Optimierung zu deaktivieren. Und auf ELF-Zielen stellt GCC die Debug-Informationen in separate Abschnitte, so dass sie nicht einmal von der Festplatte geladen werden, bis sie benötigt werden. – janneb

Antwort

12

Kompilieren mit der -g Option zu gcc tut nicht verursachen eine "Leistungsreduzierung". Es bewirkt nur, dass Debugging-Symbole eingefügt werden. es tut nicht beeinflussen die Optimierung oder Code-Generierung.

Wenn Sie Ihren SIGSEGV Handler mit dem sa_sigaction Mitglied der sigaction Struktur installieren weitergegeben sigaction(), dann ist das si_addr Mitglied der Struktur siginfo_t an Ihren Handler übergab die Verwerfungen Adresse enthält.

+1

Ich hatte Probleme, wo ein segfault, der durch das Schreiben auf einen nicht initialisierten Zeiger verursacht wurde, erschien und verschwand, je nachdem, ob ich -g oder was -o level hatte . Es hat damit zu tun, was Erinnerung wo ist. Genauso hatte ich das Hinzufügen oder Löschen eines Prints, bei dem der Fehler auftrat. Segfaults in C können schlaue Bastarde sein. –

1

Dies scheint http://tlug.up.ac.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV

static void signal_segv(int signum, siginfo_t* info, void*ptr) { 
// info->si_addr is the illegal address 
} 
+0

'info-> si_addr' ist die fehlerhafte Speicheradresse. Wie in dem von Ihnen angegebenen Link angegeben, kann die Adresse zu dem Zeitpunkt, an dem das Signal ausgelöst wurde, von "void * ptr" abgerufen werden. Siehe meine Antwort hier für Code, den ich mit ARM verwendet habe - http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes/1925461#1925461 – jschmier

3

ich valgrind zu verwenden neigen dazu, zu arbeiten, die Lecks und Speicherzugriffsfehler anzeigt.

+0

Valgrind ist für X86, AMD64 und PPC - der Frager läuft auf ARM. Ich bin jedoch angenehm überrascht zu lesen, dass der ARM-Support in Arbeit ist. – crazyscot

+0

@crazyscot Ich habe tatsächlich den "Arm" Teil der Frage verpasst.Aber schön zu wissen Valgrind ist dabei, diese Architektur zu unterstützen;) – ereOn

1

Wenn Sie sich Sorgen über die Verwendung von -g auf der Binärdatei, die Sie auf dem Gerät laden, können Sie gdbserver auf dem ARM-Gerät mit einer stripped Version der ausführbaren Datei verwenden und Arm-GDB auf Ihrem Entwicklungscomputer mit ausführen die nicht abgestreifte Version der ausführbaren Datei. Die abgestreifte Version und die unstripped Version benötigen bis zu entsprechen, dies zu tun, so tun dies:

# You may add your own optimization flags 
arm-gcc -g program.c -o program.debug 
arm-strip --strip-debug program.debug -o program 
# or 
arm-strip --strip-unneeded program.debug -o program 

Sie finden die GDB und gdbserver Dokumentation lesen müssen, um herauszufinden, wie sie zu verwenden. Es ist nicht so schwierig, aber es ist nicht so poliert wie es sein könnte. Hauptsächlich ist es sehr einfach, gdb versehentlich zu sagen, etwas zu tun, von dem man denkt, dass es lokal ausgeführt werden sollte, so dass es aus dem Remote-Debugging-Modus ausschaltet.

1

Sie können auch die Funktion backtrace() verwenden, falls verfügbar, die zum Zeitpunkt des Absturzes den Aufruf-Stack bereitstellt. Dies kann verwendet werden, um den Stapel abzulegen, wie es in einer höheren Programmiersprache geschieht, wenn ein C-Programm einen Segmentierungsfehler, einen Busfehler oder einen anderen Speicherverletzungsfehler erhält.

Backtrace() ist sowohl auf Linux und Mac OS X

0

verfügbar, wenn die Option -g der Fehler, wohl wissend, dann verschwinden läßt, wo es abstürzt ist unwahrscheinlich, nützlich sowieso sein. Es wird wahrscheinlich auf einen nicht initialisierten Zeiger in Funktion A geschrieben, und dann versucht Funktion B, diesen Speicher legitim zu verwenden und stirbt. Gedächtnisfehler sind ein Schmerz.

Verwandte Themen