How to get a "bus error"?
Asked Answered
R

12

18

I am trying very hard to get a bus error.

One way is misaligned access and I have tried the examples given here and here, but no error for me - the programs execute just fine.

Is there some situation which is sure to produce a bus error?

Redraft answered 15/1, 2010 at 4:6 Comment(3)
What platform and hardware architecture are you using?Punishment
it should be noted that by default x86 will not have a bus error, instead it will work but the memory access will be not as performant as an aligned read. on the other hand SPARC arches do have a bus error.World
No, see Michael Burr's comments and my answer. Even on x86, you can get a bus error by attempting to access memory which does not exist (as opposed to a segmentation fault, which comes from a violation of access policy).Omnifarious
M
11

Bus errors can only be invoked on hardware platforms that:

  1. Require aligned access, and
  2. Don't compensate for an unaligned access by performing two aligned accesses and combining the results.

You probably do not have access to such a system.

Marutani answered 15/1, 2010 at 4:9 Comment(11)
is there some way to be sure of that?Redraft
@eSKay: If you're using an Intel CPU, which means basically any personal computer nowadays, you will never get a bus error from misaligned access. If you're using PowerPC, SPARC, etc., then you can cause a bus error that way.Searle
Do you have any SPARC or MIPS equipment?Marutani
That's not an equivalent. In fact, it's the first CPU Chris said can't have a bus error from misaligned access.Larhondalari
x86-class Intel machines allow unaligned accesses. Try an Itanium.Marutani
@eSKay, it's a fundamental part of how the hardware architecture works. On x86 compatible machines, there is no way to generate a fault from unaligned access. The only way you can tell is that unaligned access takes longer, and even then I think that only happens if the memory isn't in your L1 cache already.Daliadalila
The 8086 allowed unaligned access, and every x86 processor since has supported that feature (with plenty of extra transistors) to maintain compatibility. It's not going away. Also, a readily available processor that you could get a bus error on is the Cell processor in the Sony PS3, since it is based on the POWER architecture (same as the PowerPC).Slumber
There are typically other ways a bus error can occur than just unaligned memory access. It's very platform specific as to what causes a bus error (or even exactly what constitutes a bus error).Armageddon
Also, strictly speaking an unaligned access on an Itanium will generate an "Unaligned Data Reference" fault. Strictly speaking it's not a bus fault, though the OS may decide to describe it as one. (and even on Itanium, it can be configured to allow most unaligned accesses without faulting, except those that cross an 8 byte boundary).Armageddon
See my answer https://mcmap.net/q/651033/-how-to-get-a-quot-bus-error-quot/… for an easy way to get a bus error on a modern system (2009 C2D, Darwin 10.5.8)Vial
In my experience, even prohibited unaligned access on x86 (for example with SSE2 128 bit SIMD registers) results in segmentation violations and not bus errors.Withdrew
O
20

This should reliably result in a SIGBUS on a POSIX-compliant system.

#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
int main() {
    FILE *f = tmpfile();
    int *m = mmap(0, 4, PROT_WRITE, MAP_PRIVATE, fileno(f), 0);
    *m = 0;
    return 0;
}

From the Single Unix Specification, mmap:

References within the address range starting at pa and continuing for len bytes to whole pages following the end of an object shall result in delivery of a SIGBUS signal.

Omnifarious answered 15/1, 2010 at 6:10 Comment(4)
Nice find. I've verified that this causes a bus error on both openSUSE 11.1 and Darwin 10.2.0 (i.e. Mac OS x 10.6.2).Punishment
I know this is an old thread but.. Can anyone explain why this causes a bus error? I understand that the bus error occurs on the line *m = 0;, but I don't see how it is related to the explanation of the SIGBUS signal raised quoted in this answer..Navarra
@Navarra when you replied to this is was over 6 years old, now your comment itself is over 6 years old, but I came across it and wanted to answer. mmap can map a region longer than the underlying file, also I think it will map whole pages. So when we do mmap 4 on the file which is not 4 bytes long and the write to this memory it triggers the SIGBUS.Chayachayote
Accidentally submitted the comment and can no longer edit it, but here is an example: gist.github.com/jcul/8b8385624977564a87fd9381e24217b1Chayachayote
M
11

Bus errors can only be invoked on hardware platforms that:

  1. Require aligned access, and
  2. Don't compensate for an unaligned access by performing two aligned accesses and combining the results.

You probably do not have access to such a system.

Marutani answered 15/1, 2010 at 4:9 Comment(11)
is there some way to be sure of that?Redraft
@eSKay: If you're using an Intel CPU, which means basically any personal computer nowadays, you will never get a bus error from misaligned access. If you're using PowerPC, SPARC, etc., then you can cause a bus error that way.Searle
Do you have any SPARC or MIPS equipment?Marutani
That's not an equivalent. In fact, it's the first CPU Chris said can't have a bus error from misaligned access.Larhondalari
x86-class Intel machines allow unaligned accesses. Try an Itanium.Marutani
@eSKay, it's a fundamental part of how the hardware architecture works. On x86 compatible machines, there is no way to generate a fault from unaligned access. The only way you can tell is that unaligned access takes longer, and even then I think that only happens if the memory isn't in your L1 cache already.Daliadalila
The 8086 allowed unaligned access, and every x86 processor since has supported that feature (with plenty of extra transistors) to maintain compatibility. It's not going away. Also, a readily available processor that you could get a bus error on is the Cell processor in the Sony PS3, since it is based on the POWER architecture (same as the PowerPC).Slumber
There are typically other ways a bus error can occur than just unaligned memory access. It's very platform specific as to what causes a bus error (or even exactly what constitutes a bus error).Armageddon
Also, strictly speaking an unaligned access on an Itanium will generate an "Unaligned Data Reference" fault. Strictly speaking it's not a bus fault, though the OS may decide to describe it as one. (and even on Itanium, it can be configured to allow most unaligned accesses without faulting, except those that cross an 8 byte boundary).Armageddon
See my answer https://mcmap.net/q/651033/-how-to-get-a-quot-bus-error-quot/… for an easy way to get a bus error on a modern system (2009 C2D, Darwin 10.5.8)Vial
In my experience, even prohibited unaligned access on x86 (for example with SSE2 128 bit SIMD registers) results in segmentation violations and not bus errors.Withdrew
O
7

Try something along the lines of:

#include <signal.h>
int main(void)
{
    raise(SIGBUS);
    return 0;
}

(I know, probably not the answer you want, but it's almost sure to get you a "bus error"!)

Octahedrite answered 15/1, 2010 at 6:44 Comment(0)
A
3

As others have mentioned this is very platform specific. On the ARM system I'm working with (which doesn't have virtual memory) there are large portions of the address space which have no memory or peripheral assigned. If I read or write one of those addresses, I get a bus error.

You can also get a bus error if there's actually a hardware problem on the bus.

If you're running on a platform with virtual memory, you might not be able to intentionally generate a bus error with your program unless it's a device driver or other kernel mode software. An invalid memory access would likely be trapped as an access violation or similar by the memory manager (and it never even has a chance to hit the bus).

Armageddon answered 15/1, 2010 at 6:20 Comment(0)
T
3

on linux with an Intel CPU try this:

int main(int argc, char **argv)
{
# if defined i386
    /* enable alignment check (AC) */
    asm("pushf; "
    "orl $(1<<18), (%esp); "
    "popf;");
# endif

    char d[] = "12345678";  /* yep! - causes SIGBUS even on Linux-i386 */
    return 0;
}

the trick here is to set the "alignment check" bit in one of the CPUs "special" registers.

see also: here

Tracery answered 17/2, 2010 at 15:29 Comment(0)
C
3

I am sure that you must be using x86 machines. X86 cpu does not generate bus error unless its AC flag in EFALAGS register is set.

Try this code:

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

int main(void)
{
    char *p;

    __asm__("pushf\n"
            "orl $0x40000, (%rsp)\n"
            "popf");

    /* 
     * malloc() always provides aligned memory.
     * Do not use stack variable like a[9], depending on the compiler you use,
     * a may not be aligned properly.
     */
    p = malloc(sizeof(int) + 1);
    memset(p, 0, sizeof(int) + 1);

    /* making p unaligned */
    p++;

    printf("%d\n", *(int *)p);

    return 0;
}

More about this can be found at http://orchistro.tistory.com/206

Chandrachandragupta answered 7/12, 2011 at 9:10 Comment(1)
I tried this experiment on my machine, and I got a SIGBUS. But then I removed all of the lines except the __asm__ line and the return 0; and I still get a SIGBUS. So there must be some other unaligned access happening, perhaps from the CRT library.Withdrew
J
1

Also keep in mind that some operating systems report "bus error" for errors other than misaligned access. You didn't mention in your question what it was you were actually trying to acheive. Maybe try thus:

int *x = 0;
*x=1;

the Wikipedia page you linked to mentions that access to non-existant memory can also result is a bus error. You might have better luck with loading a known-invalid address into a pointer and dereferwncing that.

Jempty answered 15/1, 2010 at 5:53 Comment(0)
E
1

How about this? untested.

  #include<stdio.h>

    typedef struct
    {
    int a;
    int b;
    } busErr;

    int main()
    {
    busErr err;
    char * cPtr;
    int *iPtr;
    cPtr = (char *)&err;
    cPtr++;
    iPtr = (int *)cPtr;
    *iPtr = 10;
    } 
Empanel answered 15/1, 2010 at 7:24 Comment(0)
H
1
int main(int argc, char **argv)
{
    char *bus_error = new char[1];
    for (int i=0; i<1000000000;i++) {
        bus_error += 0xFFFFFFFFFFFFFFF;
    *(bus_error + 0xFFFFFFFFFFFFFF) = 'X';
    }
}

Bus error: 10 (core dumped)

Hubing answered 22/3, 2013 at 14:39 Comment(0)
H
1

For 0x86 arch:

#include <stdio.h>

int main()
{
#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
    /* Enable Alignment Checking on x86_64 */
    __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

    int b = 0;
    int a = 0xffffff;
    char *c = (char*)&a;
    c++;
    int *p = (int*)c;
    *p = 10;  //Bus error as memory accessed by p is not 4 or 8 byte aligned
    printf ("%d\n", sizeof(a));
    printf ("%x\n", *p);
    printf ("%x\n", p);
    printf ("%x\n", &a);
}

Note:If asm instructions are removed, code wont generate the SIGBUS error as suggested by others. SIGBUS can occur for other reason too.

Hoedown answered 18/4, 2018 at 14:4 Comment(0)
C
0

Simple, write to memory that isn't yours:

int main()
{
    char *bus_error = 0;

    *bus_error = 'X';
}

Instant bus error on my PowerPC Mac [OS X 10.4, dual 1ghz PPC7455's], not necessarily on your hardware and/or operating system.

There's even a wikipedia article about bus errors, including a program to make one.

Cleavable answered 15/1, 2010 at 4:21 Comment(6)
On modern hardware that results in a segmentation fault, not a bus error.Marutani
This was compiled on my PowerPC mac, fairly "modern". But the same code on my two handy x86 machines segfaults, you're right.Cleavable
This depends on your OS and configuration, too -- if I run this on my PowerPC Mac running Linux, I get a SIGSEGV. OS X likes to give SIGBUS in more situations than Linux does; it's not like POSIX always mandates one signal or the other...Omnifarious
Just ran the code from his second link my my PPC64 mac, no error.Bailiwick
I can make the Mac segfault too, I just have to change the pointer to something like 0x08000000. My Ubuntu box doesn't even define SIGBUS in <signal.h>.Cleavable
@Seth: That's because with Glibc's headers, it's defined in <bits/signum.h>, included by <signal.h>.Omnifarious
B
-1

Bus errors occur if you try to access memory that is not addressable by your computer. For example, your computer's memory has an address range 0x00 to 0xFF but you try to access a memory element at 0x0100 or greater.

In reality, your computer will have a much greater range than 0x00 to 0xFF.

To answer your original post:

Tell me some situation which is sure to produce a bus error.

In your code, index into memory way outside the scope of the max memory limit. I dunno ... use some kind of giant hex value 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF indexed into a char* ...

Brooklet answered 15/1, 2010 at 6:1 Comment(1)
A "giant hex value" like that will overflow when it's fit into the <word size> pointer. Most operating systems should protect inaccessible memory anyway so you'll just hit a SIGSEGV rather than a bus error.Interlunar

© 2022 - 2024 — McMap. All rights reserved.