¿Qué es un error de autobús? ¿Es diferente de una falla de segmentación?

Resuelto raldi asked hace 16 años • 17 respuestas

¿Qué significa el mensaje "error de bus" y en qué se diferencia de un error de segmentación ?

raldi avatar Oct 17 '08 21:10 raldi
Aceptado

Los errores de bus son raros hoy en día en x86 y ocurren cuando su procesador ni siquiera puede intentar el acceso a la memoria solicitado, generalmente:

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

Las fallas de segmentación ocurren al acceder a una memoria que no pertenece a su proceso. Son muy comunes y suelen ser el resultado de:

  • usando un puntero a algo que fue desasignado.
  • usando un puntero no inicializado y por lo tanto falso.
  • usando un puntero nulo.
  • desbordando un buffer.

PD: Para ser más precisos, no es la manipulación del puntero lo que causará problemas. Está accediendo a la memoria a la que apunta (desreferenciación).

bltxd avatar Oct 17 '2008 15:10 bltxd

Un error de segmentación es acceder a una memoria a la que no tienes permitido acceder. Es de solo lectura, no tienes permiso, etc...

Un error de bus intenta acceder a una memoria que no es posible que esté allí. Ha utilizado una dirección que no tiene sentido para el sistema o el tipo de dirección incorrecto para esa operación.

Clinton Pierce avatar Oct 17 '2008 14:10 Clinton Pierce

mmapejemplo mínimo de POSIX 7

El "error de bus" ocurre cuando el kernel envía SIGBUSa un proceso.

Un mínimo ejemplo que lo produce porque ftruncatequedó en el olvido:

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

Corre con:

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

Probado en Ubuntu 14.04.

POSIX describe SIGBUS como:

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

La especificación mmap dice que:

Las referencias dentro del rango de direcciones que comienzan en pa y continúan por len bytes hasta páginas completas 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 *map = 0estamos tocando más allá del final del objeto asignado.

Accesos a memoria de pila no alineados en ARMv8 aarch64

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

Todo lo que necesitas es un programa aarch64 independiente:

.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

Luego, ese programa genera SIGBUS en Ubuntu 18.04 aarch64, kernel de Linux 4.15.0 en una máquina servidor ThunderX2 .

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

La falla parece ser opcional y controlada por los campos SCTLR_ELx.SAy SCTLR_EL1.SA0. He resumido los documentos relacionados un poco más aquí .

Creo que el kernel genera SIGBUS cuando una aplicación muestra una desalineación de datos en el bus de datos. Creo que dado que la mayoría [?] de los compiladores modernos para la mayoría de los procesadores rellenan/alinean los datos para los programadores, los problemas de alineación de antaño (al menos) se mitigaron y, por lo tanto, uno no ve SIGBUS con demasiada frecuencia en estos días (AFAIK).

De aquí

Oli avatar Oct 17 '2008 14:10 Oli