Domanda

Cosa significa "errore bus" " messaggio significa e in cosa differisce da un segfault?

È stato utile?

Soluzione

Gli errori del bus sono rari al giorno d'oggi su x86 e si verificano quando il processore non può nemmeno tentare l'accesso alla memoria richiesto, in genere:

  • utilizzando un'istruzione del processore con un indirizzo che non soddisfa i suoi requisiti di allineamento.

Gli errori di segmentazione si verificano quando si accede alla memoria che non appartiene al processo, sono molto comuni e sono in genere il risultato di:

  • usando un puntatore a qualcosa che è stato deallocato.
  • usando un puntatore falso quindi non inizializzato.
  • usando un puntatore null.
  • overflow di un buffer.

PS: per essere più precisi, questo non sta manipolando il puntatore stesso che causerà problemi, sta accedendo alla memoria a cui punta (dereferenziazione).

Altri suggerimenti

Un segfault sta accedendo alla memoria a cui non ti è permesso accedere. È di sola lettura, non hai i permessi, ecc ...

Un errore del bus sta tentando di accedere alla memoria che non può essere presente. Hai utilizzato un indirizzo privo di significato per il sistema o un tipo di indirizzo errato per tale operazione.

  

Credo che il kernel rilanci SIGBUS   quando un'applicazione mostra dati   disallineamento sul bus dati. credo   che dalla maggior parte dei compilatori [?] moderni   per la maggior parte dei processori pad / allinea il   dati per i programmatori, il   problemi di allineamento di un tempo (almeno)   mitigato, e quindi non si vede   SIGBUS troppo spesso in questi giorni (AFAIK).

Da: Qui

mmap esempio POSIX 7 minimo

" Errore bus " succede quando il kernel invia SIGBUS a un processo.

Un esempio minimo che lo produce perché ftruncate è stato dimenticato:

#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;
}

Esegui con:

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

Testato in Ubuntu 14.04.

POSIX descrive SIGBUS come:

  

Accesso a una parte indefinita di un oggetto memoria.

Le mmap spec afferma che:

  

I riferimenti all'interno dell'intervallo di indirizzi che iniziano con pa e continuano per len byte a pagine intere dopo la fine di un oggetto devono generare un segnale SIGBUS.

E shm_open dice che genera oggetti di dimensione 0:

  

L'oggetto memoria condivisa ha una dimensione pari a zero.

Quindi in * map = 0 stiamo toccando oltre la fine dell'oggetto assegnato.

Accesso alla memoria stack non allineato in ARMv8 aarch64

Questo è stato menzionato in: Che cos'è un errore del bus? per SPARC, ma qui fornirò un esempio più riproducibile.

Tutto ciò che serve è un programma aarch64 indipendente:

.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

Quel programma genera quindi SIGBUS su Ubuntu 18.04 aarch64, kernel Linux 4.15.0 in un Macchina server ThunderX2 .

Sfortunatamente, non riesco a riprodurlo in modalità utente QEMU v4.0.0, non sono sicuro del perché.

L'errore sembra essere facoltativo e controllato dai campi SCTLR_ELx.SA e SCTLR_EL1.SA0 , ho riassunto i documenti correlati un po 'più avanti .

Puoi anche ottenere SIGBUS quando per qualche motivo non è possibile effettuare il paging di una tabella codici.

Un'istanza classica di un errore del bus si trova su alcune architetture, come SPARC ( almeno alcuni SPARC, forse questo è stato modificato), è quando si fa un accesso errato. Ad esempio:

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

Questo frammento tenta di scrivere il valore intero a 32 bit 0xdeadf00d su un indirizzo (molto probabilmente) non correttamente allineato e genererà un errore di bus su architetture che sono "picky". a questo proposito. Intel x86 è, tra l'altro, non una tale architettura, consentirebbe l'accesso (anche se eseguirlo più lentamente).

Dipende dal tuo sistema operativo, CPU, compilatore e forse altri fattori.

In generale significa che il bus della CPU non è stato in grado di completare un comando o ha subito un conflitto, ma ciò potrebbe significare un'intera gamma di cose a seconda dell'ambiente e del codice in esecuzione.

-Adam

Normalmente significa un accesso non allineato.

Un tentativo di accedere alla memoria che non è fisicamente presente darebbe anche un errore del bus, ma non lo vedrai se stai usando un processore con una MMU e un sistema operativo che non sono buggy, perché non lo farai avere memoria inesistente associata allo spazio degli indirizzi del processo.

Un esempio specifico di un errore del bus che ho appena riscontrato durante la programmazione di C su OS X:

#include <string.h>
#include <stdio.h>

int main(void)
{
    char buffer[120];
    fgets(buffer, sizeof buffer, stdin);
    strcat("foo", buffer);
    return 0;
}

Nel caso in cui non ricordi i documenti strcat accoda il secondo argomento al primo modificando il primo argomento (capovolgi gli argomenti e funziona bene). Su Linux questo dà un errore di segmentazione (come previsto), ma su OS X dà un errore del bus. Perché? Davvero non lo so.

Stavo ricevendo un errore del bus quando la directory principale era al 100%.

La mia ragione per l'errore del bus su Mac OS X era che ho provato ad allocare circa 1 Mb nello stack. Questo ha funzionato bene in un thread, ma quando si utilizza openMP questo porta a errori di bus, perché Mac OS X ha un limite dimensione dello stack per thread non principali .

Per aggiungere a ciò che ha risposto blxtd sopra, si verificano anche errori del bus quando il processo non può tentare di accedere alla memoria di una particolare 'variabile' .

for (j = 0; i < n; j++) {
                for (i =0; i < m; i++) {
                        a[n+1][j] += a[i][j];
                }
        }

Nota l'uso ' involontario ' della variabile 'i' nel prima "for loop"? Questo è ciò che causa l'errore del bus in questo caso.

Ho appena scoperto che su un processore ARMv7 puoi scrivere del codice che ti dà un errore di segmentazione quando non ottimizzato, ma ti dà un errore del bus quando compilato con -O2 (ottimizza di più). Sto usando il compilatore cross gcc arm gnueabihf da Ubuntu x64.

Sono d'accordo con tutte le risposte sopra. Ecco i miei 2 centesimi per quanto riguarda l'errore BUS:

Un errore BUS non deve derivare dalle istruzioni all'interno del codice del programma. Questo può accadere quando si esegue un binario e durante l'esecuzione, il binario viene modificato (sovrascritto da una build o eliminato, ecc.).

Verifica in questo caso: Un modo semplice per verificare se questa è la causa è avviando istanze in esecuzione dello stesso binario ed eseguendo una build. Entrambe le istanze in esecuzione si arresterebbero in modo anomalo con un errore SIGBUS poco dopo il completamento della compilazione e la sostituzione del file binario (quello su cui entrambe le istanze sono attualmente in esecuzione)

Motivo sottostante: Questo perché il sistema operativo scambia le pagine di memoria e in alcuni casi l'intero binario potrebbe essere in memoria e questi arresti anomali potrebbero verificarsi quando il sistema operativo tenta di recuperare la pagina successiva dallo stesso binario, ma il binario è cambiato dall'ultima lettura.

Un tipico overflow del buffer che provoca un errore del bus è,

{
    char buf[255];
    sprintf(buf,"%s:%s\n", ifname, message);
}

Qui se la dimensione della stringa tra virgolette doppie (" ") è maggiore della dimensione buf, si ottiene un errore del bus.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top