Was ist ein Busfehler? Unterscheidet es sich von einem Segmentierungsfehler?

Lesezeit: 9 Minuten

Benutzeravatar von raldi
raldi

Was bedeutet die Meldung „Busfehler“ und wie unterscheidet sie sich von a Segmentierungsfehler?

  • Ich möchte für beide eine einfache Erklärung hinzufügen: Segmentierungsfehler bedeutet, dass Sie versuchen, auf Speicher zuzugreifen, auf den Sie nicht berechtigt sind (z. B. ist er nicht Teil Ihres Programms). Ein Busfehler bedeutet jedoch normalerweise, dass Sie versuchen, auf Speicher zuzugreifen, der nicht vorhanden ist (z. B. Sie versuchen, auf eine Adresse mit 12 GB zuzugreifen, aber Sie haben nur 8 GB Speicher) oder wenn Sie die Grenze des nutzbaren Speichers überschreiten.

    – xdevs23

    3. Oktober 2017 um 13:45 Uhr

  • Auf welcher Plattform hast du das gesehen? PC? Mac? x86? 32/64?

    – Peter Mortensen

    13. Januar 2020 um 13:11 Uhr

Benutzeravatar von bltxd
bltxd

Busfehler sind heutzutage auf x86 selten und treten auf, wenn Ihr Prozessor den angeforderten Speicherzugriff nicht einmal versuchen kann, typischerweise:

  • Verwenden einer Prozessoranweisung mit einer Adresse, die ihre Ausrichtungsanforderungen nicht erfüllt.

Segmentierungsfehler treten auf, wenn auf Speicher zugegriffen wird, der nicht zu Ihrem Prozess gehört. Sie sind sehr häufig und sind typischerweise das Ergebnis von:

  • Verwenden eines Zeigers auf etwas, das freigegeben wurde.
  • Verwenden eines nicht initialisierten, daher falschen Zeigers.
  • mit einem Nullzeiger.
  • Überlaufen eines Puffers.

PS: Genauer gesagt, es ist nicht die Manipulation des Zeigers selbst, die Probleme verursachen wird. Es greift auf den Speicher zu, auf den es zeigt (Dereferenzierung).

  • Sie sind nicht selten; Ich bin gerade bei Übung 9 von How to Learn C the Hard Way und bin schon auf eine gestoßen …

    – 11684

    26. März 2013 um 20:12 Uhr

  • Eine weitere Ursache für Busfehler (jedenfalls unter Linux) ist, wenn das Betriebssystem eine virtuelle Seite nicht mit physischem Speicher unterstützen kann (z. B. Bedingungen mit wenig Arbeitsspeicher oder keine riesigen Seiten bei Verwendung von riesigem Seitenspeicher). Typischerweise nur mmap (und malloc). Reservieren Sie den virtuellen Adressraum, und der Kernel weist den physischen Speicher nach Bedarf zu (sogenannte weiche Seitenfehler). Machen Sie ein Malloc, das groß genug ist, und schreiben Sie dann genug davon, und Sie erhalten einen Busfehler.

    – Elof

    14. Juli 2015 um 0:09 Uhr


  • für mich die Partition enthält /var/cache war einfach voll askubuntu.com/a/915520/493379

    – c33s

    15. Mai 2017 um 22:08 Uhr

  • In meinem Fall eine Methode static_casted a void * -Parameter zu einem Objekt, das einen Callback speichert (ein Attribut zeigt auf das Objekt und das andere auf die Methode). Dann wird der Rückruf aufgerufen. Was jedoch als weitergegeben wurde void * war etwas ganz anderes und somit verursachte der Methodenaufruf den Busfehler.

    – Christoph K.

    15. August 2018 um 13:04 Uhr

  • @bltxd Kennen Sie die Art von Busfehlern. dh hat die Nachricht auf dem Ringbus einen Mechanismus, bei dem eine Haltestelle auf dem Ring auch eine Nachricht akzeptiert, die von ihr gesendet wurde, aber an welches Ziel auch immer, da dies darauf hindeutet, dass sie den ganzen Weg um den Ring gegangen ist und nicht akzeptiert wurde. Ich vermute, der Zeilenfüllpuffer gibt einen Fehlerstatus zurück, und wenn er sich zurückzieht, löscht er die Pipeline und ruft die richtige Ausnahme-Mikroroutine auf. Dies erfordert grundsätzlich, dass der Speichercontroller alle Adressen in seinem Bereich akzeptiert, was darauf hindeuten würde, dass er dies intern tun müsste, wenn die BARs usw. geändert werden

    – Lewis Kelsey

    10. März 2019 um 5:00 Uhr

Ein Segfault greift auf Speicher zu, auf den Sie nicht zugreifen dürfen. Es ist schreibgeschützt, Sie haben keine Berechtigung usw.

Ein Busfehler versucht, auf Speicher zuzugreifen, der unmöglich dort sein kann. Sie haben eine Adresse verwendet, die für das System bedeutungslos ist, oder die falsche Art von Adresse für diesen Vorgang.

Ciro Santilli Benutzeravatar von OurBigBook.com
Ciro Santilli OurBigBook.com

mmap minimales POSIX 7-Beispiel

“Bus error” tritt auf, wenn der Kernel sendet SIGBUS zu einem Prozess.

Ein Minimalbeispiel, das es denn hergibt ftruncate wurde vergessen:

#include <fcntl.h> /* O_ constants */
#include <unistd.h> /* ftruncate */
#include <sys/mman.h> /* mmap */

int main() {
    int fd;
    int *map;
    int size = sizeof(int);
    char *name = "/a";

    shm_unlink(name);
    fd = shm_open(name, O_RDWR | O_CREAT, (mode_t)0600);
    /* THIS is the cause of the problem. */
    /*ftruncate(fd, size);*/
    map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    /* This is what generates the SIGBUS. */
    *map = 0;
}

Laufen mit:

gcc -std=c99 main.c -lrt
./a.out

Getestet unter Ubuntu 14.04.

Posix beschreibt SIGBUS wie:

Zugriff auf einen undefinierten Teil eines Speicherobjekts.

Das mmap spez sagt, dass:

Verweise innerhalb des Adressbereichs beginnend bei pa und weiter für len Bytes auf ganze Seiten nach dem Ende eines Objekts führen zur Lieferung eines SIGBUS-Signals.

Und shm_open sagt, dass es erzeugt Objekte der Größe 0:

Das gemeinsam genutzte Speicherobjekt hat eine Größe von Null.

Also bei *map = 0 wir berühren das Ende des zugewiesenen Objekts.

Nicht ausgerichtete Stapelspeicherzugriffe in ARMv8 aarch64

Dies wurde erwähnt bei: Was ist ein Busfehler? für SPARC, aber hier werde ich ein besser reproduzierbares Beispiel liefern.

Alles, was Sie brauchen, ist ein freistehendes aarch64-Programm:

.global _start
_start:
asm_main_after_prologue:
    /* misalign the stack out of 16-bit boundary */
    add sp, sp, #-4
    /* access the stack */
    ldr w0, [sp]

    /* exit syscall in case SIGBUS does not happen */
    mov x0, 0
    mov x8, 93
    svc 0

Dieses Programm wirft dann SIGBUS auf Ubuntu 18.04 aarch64, Linux-Kernel 4.15.0 in ein ThunderX2-Servermaschine.

Leider kann ich es im Benutzermodus von QEMU v4.0.0 nicht reproduzieren, ich bin mir nicht sicher warum.

Der Fehler scheint optional zu sein und wird von der gesteuert SCTLR_ELx.SA und SCTLR_EL1.SA0 Felder habe ich die zugehörigen Dokumente zusammengefasst hier etwas weiter.

Ich glaube, der Kernel löst SIGBUS aus, wenn eine Anwendung eine Datenfehlausrichtung auf dem Datenbus aufweist. Ich denke das seit den meisten[?] Moderne Compiler für die meisten Prozessoren füllen / richten die Daten für die Programmierer aus, die Alignment-Probleme von früher (zumindest) gemildert, und daher sieht man SIGBUS heutzutage nicht mehr allzu oft (AFAIK).

Aus: Hier

Joshuas Benutzeravatar
Josua

An Posix Systemen können Sie das SIGBUS-Signal auch erhalten, wenn eine Codepage aus irgendeinem Grund nicht eingeblättert werden kann.

  • Dies passiert häufig, wenn ich die .so-Datei aktualisiere, während der Prozess ausgeführt wird

    – schlechter Entwickler

    11. August 2015 um 2:05 Uhr

  • Ein weiterer Grund dafür ist, wenn Sie es versuchen mmap eine Datei größer als die Größe von /dev/shm

    – ilija139

    22. März 2017 um 4:57 Uhr

Ich stimme allen obigen Antworten zu. Hier sind meine 2 Cent zum BUS-Fehler:

Ein BUS-Fehler muss nicht von den Anweisungen innerhalb des Programmcodes herrühren. Dies kann passieren, wenn Sie eine Binärdatei ausführen und während der Ausführung die Binärdatei geändert wird (durch einen Build überschrieben oder gelöscht usw.).

Überprüfen, ob dies der Fall ist

Eine einfache Möglichkeit, zu überprüfen, ob dies die Ursache ist, besteht darin, ein paar Instanzen derselben Binärdatei aus einem Build-Ausgabeverzeichnis zu starten und nach dem Start einen Build auszuführen. Beide laufenden Instanzen würden mit a abstürzen SIGBUS Fehler kurz nachdem der Build abgeschlossen ist und die Binärdatei ersetzt hat (diejenige, die beide Instanzen derzeit ausführen).

Zugrunde liegender Grund

Dies liegt daran, dass das Betriebssystem Speicherseiten austauscht und in einigen Fällen die Binärdatei möglicherweise nicht vollständig in den Speicher geladen wird. Diese Abstürze treten auf, wenn das Betriebssystem versucht, die nächste Seite aus derselben Binärdatei abzurufen, die Binärdatei jedoch seit dem letzten Lesen geändert wurde.

  • Dies passiert häufig, wenn ich die .so-Datei aktualisiere, während der Prozess ausgeführt wird

    – schlechter Entwickler

    11. August 2015 um 2:05 Uhr

  • Ein weiterer Grund dafür ist, wenn Sie es versuchen mmap eine Datei größer als die Größe von /dev/shm

    – ilija139

    22. März 2017 um 4:57 Uhr

Benutzeravatar von Peter Mortensen
Peter Mortensen

Eine klassische Instanz eines Busfehlers tritt auf bestimmten Architekturen auf, wie z SPARC (zumindest einige SPARCs, vielleicht wurde dies geändert), wenn Sie einen falsch ausgerichteten Zugriff vornehmen. Zum Beispiel:

unsigned char data[6];
(unsigned int *) (data + 2) = 0xdeadf00d;

Dieses Snippet versucht, den 32-Bit-Ganzzahlwert zu schreiben 0xdeadf00d an eine Adresse, die (höchstwahrscheinlich) nicht richtig ausgerichtet ist, und erzeugt einen Busfehler auf Architekturen, die in dieser Hinsicht “wählerisch” sind. Der Intel x86 ist übrigens nicht so eine Architektur. Es würde den Zugriff erlauben (wenn auch langsamer ausführen).

  • Falls ich Daten hatte[8]; Dies ist jetzt ein Vielfaches von 4 in einer 32-Bit-Architektur. Es ist also ausgerichtet. Bekomme ich den Fehler jetzt immer noch? Bitte erklären Sie auch, ob eine Datentypkonvertierung für Zeiger eine schlechte Idee ist. Wird es bei einer fragilen Architektur zu Fehlausrichtungsfehlern kommen? Bitte erläutern Sie, es wird mir helfen.

    – geschickt

    1. Oktober 2013 um 12:49 Uhr

  • Heh. Es ist nicht so sehr eine Typkonvertierung, als dass Sie eine Typkonvertierung für einen Zeiger durchführen, für den Sie Zeigerberechnungen durchgeführt haben. Aussehen sorgfältig bei obigem Code. Der Compiler hat Ihren Zeiger für Daten sorgfältig auf DWord ausgerichtet – und dann vermasseln Sie alles am Compiler, indem Sie die Referenz um ZWEI versetzen und in einen sehr dringenden DWord-ausgerichteten Zugriff auf eine Nicht-DWord-Grenze umwandeln.

    – Svartalf

    16. Dezember 2014 um 18:28 Uhr


  • „Zerbrechlich“ ist nicht das Wort, das ich für all das verwenden würde. X86-Maschinen und -Code bringen die Leute schon seit einiger Zeit dazu, ziemlich dumme Dinge zu tun, und dies ist eines davon. Überdenken Sie Ihren Code, wenn Sie diese Art von Problem haben – er ist auf X86 zunächst nicht sehr leistungsfähig.

    – Svartalf

    16. Dezember 2014 um 18:31 Uhr

  • @Svartalf: Auf x86 sind Wortzugriffe auf nicht ausgerichtete Zeiger sicherlich langsamer als Wortzugriffe auf ausgerichtete Zeiger, aber zumindest historisch waren sie schneller als einfacher Code, der Dinge bedingungslos aus Bytes zusammensetzt, und sie sind sicherlich einfacher als Code, der es versucht um eine optimale Kombination von Operationen unterschiedlicher Größe zu verwenden. Ich wünschte, der C-Standard würde Mittel zum Packen / Entpacken größerer Ganzzahltypen in / aus einer Folge kleinerer Ganzzahlen / Zeichen enthalten, damit der Compiler den auf einer bestimmten Plattform am besten geeigneten Ansatz verwenden kann.

    – Superkatze

    17. April 2015 um 20:35 Uhr

  • @Supercat: Die Sache ist folgende: Auf X86 kommst du damit durch. Sie versuchen dies auf ARM, MIPS, Power usw. und Sie werden unangenehme Dinge erleben, die Ihnen passieren. Auf ARM weniger als Arch V7 wird Ihr Code einen Ausrichtungsfehler haben – und auf V7 können Sie, WENN Ihre Laufzeit darauf eingestellt ist, mit einem SCHWEREN Leistungseinbruch umgehen. Sie wollen das einfach nicht tun. Es sind schlechte Praktiken, um ehrlich zu sein. 😀

    – Svartalf

    23. April 2015 um 18:15 Uhr

1427250cookie-checkWas ist ein Busfehler? Unterscheidet es sich von einem Segmentierungsfehler?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy