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?

War es hilfreich?

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

waren
  

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?

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top