Busfehler vs Segmentation fault
-
22-07-2019 - |
Frage
Der Unterschied zwischen einem Bus-Fehler und einem Segmentierungsfehler? passieren kann, dass ein Programm einen Segmentation Fehler gibt und stoppt zum ersten Mal und zum zweiten Mal kann es einen Bus-Fehler und Ausfahrt geben?
Lösung
Auf den meisten Architekturen ich verwendet habe, die Unterscheidung ist, dass:
- ein SEGV verursacht, wenn Sie den Speicher zugreifen Sie auf (zum Beispiel außerhalb des Adressraums) nicht gemeint.
- a SIGBUS wird verursacht durch Ausrichtungsprobleme mit der CPU (beispielsweise versucht, eine lange von einer Adresse zu lesen, die nicht ein Vielfaches von 4 ist).
Andere Tipps
SIGBUS
wird auch, wenn Sie mmap()
eine Datei erhöht werden und versuchen, einen Teil der für den Zugriff auf der zugeordnete Puffer, der über das Ende der Datei erstreckt, sowie auf Fehlerbedingungen, wie beispielsweise aus dem Raum. Wenn Sie ein Signal-Handler registrieren mit sigaction()
und Sie setzen SA_SIGINFO
, kann es möglich sein haben Ihr Programm der fehlerhafte Speicheradresse prüfen und nur im Speicher abgebildeten Dateifehler behandeln.
Zum Beispiel könnte ein Bus-Fehler verursacht werden, wenn das Programm versucht, etwas zu tun, dass der Hardware-Bus nicht unterstützt. Auf SPARCs zum Beispiel versuchen, einen Multi-Byte-Wert (wie ein int zu lesen, 32 -Bits) aus einer ungeraden Adresse erzeugt einen Busfehler.
Segmentation Fehler passieren zum Beispiel, wenn Sie einen Zugang zu tun, die die Segmentierungsregeln verletzen, das heißt versucht, Speicher zu lesen oder schreiben, die Sie nicht besitzen.
Ich nehme an, Sie sprechen über die SIGSEGV
und SIGBUS
Signale definiert durch Posix.
SIGSEGV
tritt auf, wenn das Programm eine ungültige Adresse verweist. SIGBUS
ist eine Implementierung definiert Hardware-Fehler. Die Standardaktion für diese beiden Signale ist das Programm zu beenden.
Das Programm kann diese Signale fangen, und sie sogar ignorieren.
Interpretieren der Frage (möglicherweise falsch) im Sinne von „Ich bin zeitweise eine SIGSEGV oder eine SIGBUS bekommen, warum ist es nicht im Einklang?“, Es ist erwähnenswert, dass zu tun zwielichtige Dinge mit Zeigern nicht durch die C gewährleistet ist oder C-Normen ++ in einem segfault zu führen; es ist nur „nicht definiertes Verhalten“, der als Professor hatte ich einmal bedeutet es setzen, dass es stattdessen Krokodile verursachen können von den Dielen entstehen und Sie essen.
So Ihre Situation könnte sein, dass Sie zwei Fehler haben, wo die erste auftreten zu manchmal verursacht SIGSEGV und die zweite (wenn der segfault ist nicht geschehen, und das Programm läuft noch) verursacht ein SIGBUS.
Ich empfehle Ihnen, mit einem Debugger Schritt durch, und halten Sie Ausschau nach Krokodilen.
Dies wäre ein dup von Was für einen Bus-Fehler ist? , wenn es nicht für die
warenKann es vorkommen, dass ein Programm einen seg Fehler gibt und stoppt zum ersten Mal und zum zweiten Mal kann es einen Bus-Fehler und Ausfahrt geben?
Teil der Frage. Sie sollten hier die Informationen für sich selbst diese beantworten können.
Insanity:. Die gleiche Sache immer und immer wieder tun und andere Ergebnisse zu erwarten
- Albert Einstein
Natürlich nimmt die Frage wörtlich ...
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main() {
srand(time(NULL));
if (rand() % 2)
kill(getpid(), SIGBUS);
else
kill(getpid(), SIGSEGV);
return 0;
}
Tada, ein Programm, das mit einem Segmentierungsfehler auf einem Durchlauf und Abfahrt mit einem Bus-Fehler auf einem anderen Laufe verlassen kann.
Kann es vorkommen, dass ein Programm einen seg Fehler gibt und stoppt zum ersten Mal und zum zweiten Mal kann es einen Bus-Fehler und Ausfahrt geben?
Ja, auch für ein und denselben Fehler: Dies ist ein ernstes, aber einfaches Beispiel aus macOS, die sowohl produzieren kann, Segmentierungsfehler (SIGSEGV) und Bus-Fehler (SIGBUS), von Indizes außerhalb der Grenzen eines Arrays, in eine deterministisch. Der nicht ausgerichtete Zugriff oben erwähnt ist nicht ein Problem mit macOS. (In diesem Beispiel wird keinen SIGBUS verursachen, wenn es in einem Debugger läuft, lldb
in meinem Fall!)
bus_segv.c:
#include <stdlib.h>
char array[10];
int main(int argc, char *argv[]) {
return array[atol(argv[1])];
}
Das Beispiel nimmt eine ganze Zahl von der Befehlszeile, die als Index für die Anordnung dient. Das sind einige der Indexwerte (auch außerhalb der Matrix), die kein Signal führt. (Alle angegebenen Werte sind abhängig von den Standard-Segment / Abschnittsgrößen. I verwendet Klirren-902.0.39.1 die binären auf einer High Sierra macOS 10.13.5, i5-4288U CPU @ 2.60GHz zu produzieren.)
Ein Index über 77791 und unter -4128 wird ein Segmentierungsfehler (SIGSEGV) verursachen. 24544 wird ein Busfehler (SIGBUS) verursachen. Die komplette Karte:
$ ./bus_segv -4129
Segmentation fault: 11
$ ./bus_segv -4128
...
$ ./bus_segv 24543
$ ./bus_segv 24544
Bus error: 10
...
$ ./bus_segv 28639
Bus error: 10
$ ./bus_segv 28640
...
$ ./bus_segv 45023
$ ./bus_segv 45024
Bus error: 10
...
$ ./bus_segv 53215
Bus error: 10
$ ./bus_segv 53216
...
$ ./bus_segv 69599
$ ./bus_segv 69600
Bus error: 10
...
$ ./bus_segv 73695
Bus error: 10
$ ./bus_segv 73696
...
$ ./bus_segv 77791
$ ./bus_segv 77792
Segmentation fault: 11
Wenn Sie an dem demontierten Code schauen, sehen Sie, dass die Grenzen der Bereiche mit Bus-Fehlern sind nicht so seltsam, wie der Index erscheint:
$ otool -tv bus_segv
bus_segv:
(__TEXT,__text) section
_main:
0000000100000f60 pushq %rbp
0000000100000f61 movq %rsp, %rbp
0000000100000f64 subq $0x10, %rsp
0000000100000f68 movl $0x0, -0x4(%rbp)
0000000100000f6f movl %edi, -0x8(%rbp)
0000000100000f72 movq %rsi, -0x10(%rbp)
0000000100000f76 movq -0x10(%rbp), %rsi
0000000100000f7a movq 0x8(%rsi), %rdi
0000000100000f7e callq 0x100000f94 ## symbol stub for: _atol
0000000100000f83 leaq 0x96(%rip), %rsi
0000000100000f8a movsbl (%rsi,%rax), %eax
0000000100000f8e addq $0x10, %rsp
0000000100000f92 popq %rbp
0000000100000f93 retq
Mit dem leaq 0x96(%rip), %rsi
wird rsi der (PC relativ
bestimmt) Adresse der Startadresse des Arrays:
rsi = 0x100000f8a + 0x96 = 0x100001020
rsi - 4128 = 0x100000000 (below segmentation fault)
rsi + 24544 = 0x100007000 (here and above bus error)
rsi + 28640 = 0x100008000 (below bus error)
rsi + 45024 = 0x10000c000 (here and above bus error)
rsi + 53216 = 0x10000e000 (below bus error)
rsi + 69600 = 0x100012000 (here and above bus error)
rsi + 73696 = 0x100013000 (below bus error)
rsi + 77792 = 0x100014000 (here and above segmentation fault)
lldb
stellt wahrscheinlich den Prozess mit verschiedenen Seiten Grenzen. Ich war nicht in der Lage, all Bus-Fehler in einer Debug-Sitzung zu reproduzieren. So ist der Debugger kann eine Abhilfe für Busfehler Spucken Binärdateien sein.
Andreas