Pregunta

¿Qué significa el " error de bus " mensaje significa, y en qué se diferencia de un segfault?

¿Fue útil?

Solución

Los errores de bus son raros hoy en día en x86 y ocurren cuando su procesador ni siquiera puede intentar acceder a la memoria solicitada, por lo general:

  • utilizando una instrucción del procesador con una dirección que no cumple con sus requisitos de alineación.

Los fallos de segmentación ocurren cuando se accede a la memoria que no pertenece a su proceso, son muy comunes y generalmente son el resultado de:

  • usando un puntero a algo que fue desasignado.
  • usando un puntero no inicializado, por lo tanto, falso.
  • usando un puntero nulo.
  • desbordando un búfer.

PD: para ser más precisos, esto no es manipular el puntero en sí mismo que causará problemas, está accediendo a la memoria a la que apunta (desreferenciación).

Otros consejos

Un segfault es acceder a la memoria a la que no se le permite acceder. Es de solo lectura, no tiene permiso, etc. ...

Un error de bus está intentando acceder a la memoria que posiblemente no puede estar allí. Ha utilizado una dirección que no tiene sentido para el sistema, o el tipo de dirección incorrecto para esa operación.

  

Creo que el kernel eleva SIGBUS   cuando una aplicación exhibe datos   Desalineación en el bus de datos. Yo creo que   que desde la mayoría de los compiladores [?] modernos   para la mayoría de los procesadores, alinee / alinee el   datos para los programadores, el   problemas de alineación de antaño (al menos)   mitigado, y por lo tanto uno no ve   SIGBUS con demasiada frecuencia en estos días (AFAIK).

De: Aquí

mmap Ejemplo de POSIX 7 mínimo

" Error de bus " sucede cuando el kernel envía SIGBUS a un proceso.

Un ejemplo mínimo que lo produce porque se olvidó ftruncate :

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

Ejecutar con:

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

Probado en Ubuntu 14.04.

POSIX describe SIGBUS as:

  

Acceso a una porción indefinida de un objeto de memoria.

El mmap spec dice que:

  

Las referencias dentro del rango de direcciones que comienzan en pa y continúan para len bytes a páginas enteras después del final de un objeto darán como resultado la entrega de una señal SIGBUS.

Y shm_open dice que genera objetos de tamaño 0:

  

El objeto de memoria compartida tiene un tamaño de cero.

Entonces, en * map = 0 estamos tocando más allá del final del objeto asignado.

Accesos de memoria de pila no alineados en ARMv8 aarch64

Esto se mencionó en: ¿Qué es un error de bus? para SPARC, pero aquí proporcionaré un ejemplo más reproducible.

Todo lo que necesita es un programa independiente aarch64:

.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

Ese programa luego genera SIGBUS en Ubuntu 18.04 aarch64, Linux kernel 4.15.0 en un máquina del servidor ThunderX2 .

Desafortunadamente, no puedo reproducirlo en el modo de usuario QEMU v4.0.0, no estoy seguro de por qué.

El error parece ser opcional y está controlado por los campos SCTLR_ELx.SA y SCTLR_EL1.SA0 , he resumido los documentos relacionados un poco más aquí .

También puede obtener SIGBUS cuando una página de códigos no puede paginarse por algún motivo.

Una instancia clásica de un error de bus se encuentra en ciertas arquitecturas, como SPARC ( al menos algunos SPARC, tal vez esto ha cambiado), es cuando haces un acceso mal alineado. Por ejemplo:

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

Este fragmento de código intenta escribir el valor entero de 32 bits 0xdeadf00d en una dirección que (probablemente) no esté correctamente alineada, y generará un error de bus en las arquitecturas que son " picky " a este respecto. El Intel x86 es, por cierto, no tal arquitectura, permitiría el acceso (aunque lo ejecute más lentamente).

Depende de su sistema operativo, CPU, compilador y posiblemente otros factores.

En general, significa que el bus de la CPU no pudo completar un comando o sufrió un conflicto, pero eso podría significar una gran variedad de cosas dependiendo del entorno y el código que se ejecuta.

-Adam

Normalmente significa un acceso no alineado.

Un intento de acceder a la memoria que no está físicamente presente también daría un error de bus, pero no verá esto si está utilizando un procesador con una MMU y un sistema operativo que no tiene errores, porque no lo hará tenga cualquier memoria no existente asignada al espacio de direcciones de su proceso.

Un ejemplo específico de un error de bus que acabo de encontrar mientras programaba C en OS X:

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

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

En caso de que no recuerdes, los documentos strcat agregan el segundo argumento al primero cambiando el primer argumento (voltea los argumentos y funciona bien). En Linux, esto da un error de segmentación (como se esperaba), pero en OS X da un error de bus. ¿Por qué? Realmente no lo sé.

Estaba recibiendo un error de bus cuando el directorio raíz estaba al 100%.

Mi razón para el error de bus en Mac OS X fue que traté de asignar aproximadamente 1Mb en la pila. Esto funcionó bien en un subproceso, pero cuando se usa openMP, esto conduce al error de bus, porque Mac OS X tiene muy limitado tamaño de pila para subprocesos no principales .

Para agregar a lo que blxtd respondió anteriormente, los errores del bus también ocurren cuando su proceso no puede intentar acceder a la memoria de una 'variable' particular .

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

Observe el uso ' inadvertido ' de variable 'i' en First 'for loop'? Eso es lo que está causando el error de bus en este caso.

Acabo de descubrir que, en un procesador ARMv7, puede escribir algo de código que le dé un fallo de segmentación cuando no esté optimizado, pero que le dé un error de bus cuando se compile con -O2 (optimizar más). Estoy usando gcc arm gnueabihf cross compiler de ubuntu x64.

Estoy de acuerdo con todas las respuestas anteriores. Aquí están mis 2 centavos con respecto al error de BUS:

Un error de BUS no debe surgir de las instrucciones dentro del código del programa. Esto puede suceder cuando está ejecutando un binario y durante la ejecución, el binario se modifica (se sobrescribe con una compilación o se elimina, etc.).

Verificando si este es el caso: Una forma sencilla de comprobar si esta es la causa es iniciar instancias en ejecución del mismo binario y ejecutar una compilación. Ambas instancias en ejecución se bloquearían con un error SIGBUS poco después de que la compilación haya finalizado y reemplazado el binario (el que está ejecutando actualmente ambas instancias)

Razón subyacente: Esto se debe a que el sistema operativo intercambia páginas de memoria y, en algunos casos, el binario completo podría estar en la memoria y estos bloqueos ocurrirían cuando el sistema operativo intente recuperar la página siguiente del mismo binario, pero el binario ha cambiado desde la última vez que lo leyó. / p>

Un desbordamiento de búfer típico que produce un error de bus es,

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

Aquí si el tamaño de la cadena entre comillas dobles (" ") es mayor que el tamaño buf, se produce un error de bus.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top