tags:

views:

544

answers:

9

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?

+7  A: 

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.

Ignacio Vazquez-Abrams
is there some way to be sure of that?
Lazer
@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.
Chris Jester-Young
Do you have any SPARC or MIPS equipment?
Ignacio Vazquez-Abrams
yes, I am using Intel P4. Any idea why no error on Intels?
Lazer
That's not an equivalent. In fact, it's the first CPU Chris said can't have a bus error from misaligned access.
GMan
x86-class Intel machines allow unaligned accesses. Try an Itanium.
Ignacio Vazquez-Abrams
@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.
Omnifarious
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).
Mike DeSimone
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).
Michael Burr
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).
Michael Burr
See my answer http://stackoverflow.com/questions/2069450/how-to-get-a-bus-error/3197333#3197333 for an easy way to get a bus error on a modern system (2009 C2D, Darwin 10.5.8)
Larry Wang
A: 

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.

Seth
On modern hardware that results in a segmentation fault, not a bus error.
Ignacio Vazquez-Abrams
This was compiled on my PowerPC mac, fairly "modern". But the same code on my two handy x86 machines segfaults, you're right.
Seth
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...
ephemient
Just ran the code from his second link my my PPC64 mac, no error.
Richo
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>`.
Seth
@Seth: That's because with Glibc's headers, it's defined in `<bits/signum.h>`, included by `<signal.h>`.
ephemient
A: 

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.

Mark Bessey
A: 

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* ...

Doug Smith
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.
Matthew Iselin
+6  A: 

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.

ephemient
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).
R Samuel Klatchko
A: 

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).

Michael Burr
+1  A: 

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"!)

Alok
A: 

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;
    } 
chappar
A: 

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