In computing, a bus error is a fault raised by hardware, notifying an operating system that a process is trying to access memory that the CPU cannot physically address: an invalid address for the address bus, hence the name. In modern use on most architectures these are much rarer than segmentation faults, which occur primarily due to memory access violations: problems in the logical address or permissions. On POSIX-compliant platforms, bus errors usually result in the SIGBUS signal being sent to the process that caused the error. SIGBUS can also be caused by any general device fault that the computer detects, though a bus error rarely means that the computer hardware is physically broken—it is normally caused by a bug in software. Bus errors may also be raised for certain other paging errors; see below.
Causes
There are at least three main causes of bus errors:
Non-existent address
Software instructs the CPU to read or write a specific physical memory address. Accordingly, the CPU sets this physical address on its address bus and requests all other hardware connected to the CPU to respond with the results, if they answer for this specific address. If no other hardware responds, the CPU raises an exception, stating that the requested physical address is unrecognized by the whole computer system. Note that this only covers physical memory addresses. Trying to access an undefined virtual memory address is generally considered to be a segmentation fault rather than a bus error, though if the MMU is separate, the processor cannot tell the difference.
Unaligned access
Most CPUs are byte-addressable, where each unique memory address refers to an 8-bit byte. Most CPUs can access individual bytes from each memory address, but they generally cannot access larger units without these units being "aligned" to a specific boundary. For example, if multi-byte accesses must be 16 bit-aligned, addresses at 0, 2, 4, 6, and so on would be considered aligned and therefore accessible, while addresses 1, 3, 5, and so on would be considered unaligned. Similarly, if multi-byte accesses must be 32-bit aligned, addresses 0, 4, 8, 12, and so on would be considered aligned and therefore accessible, and all addresses in between would be considered unaligned. Attempting to access a unit larger than a byte at an unaligned address can cause a bus error. Some systems may have a hybrid of these depending on the architecture being used. For example, for hardware based on the IBM System/360 mainframe, including the IBM System z, Fujitsu B8000, RCA Spectra, and UNIVAC Series 90, instructions must be on a 16-bit boundary, that is, execution addresses must start on an even byte. Attempts to branch to an odd address results in a specification exception. Data, however, may be retrieved from any address in memory, and may be one byte or longer depending on the instruction. CPUs generally access data at the full width of their data bus at all times. To address bytes, they access memory at the full width of their data bus, then mask and shift to address the individual byte. Systems tolerate this inefficient algorithm, as it is an essential feature for most software, especially string processing. Unlike bytes, larger units can span two aligned addresses and would thus require more than one fetch on the data bus. It is possible for CPUs to support this, but this functionality is rarely required directly at the machine code level, thus CPU designers normally avoid implementing it and instead issue bus errors for unaligned memory access.
On x86 exists an older memory management mechanism known as segmentation. If the application loads segment register with the selector of non-present segment, the exception is generated. Some OSes used that for swapping, but under Linux this generates SIGBUS.
Compiling and running the example on a POSIX compliant OS on x86 demonstrates the error: $ gcc -ansi sigbus.c -o sigbus $./sigbus Bus error $ gdb./sigbus r Program received signal SIGBUS, Bus error. 0x080483ba in main x/i $pc 0x80483ba : mov DWORD PTR ,0x2a p/x $eax $1 = 0x804a009 p/t $eax & $2 = 1