Pages

Monday, March 03, 2008

SIGBUS Vs SIGSEGV




Here is a special blog, this one talks about the subtle differences between two of Linux Signals: SIGBUS and SIGSEGV.
There are different reasons behind the generation of SIGBUS or SIGSEGV. And here we analysis the difference between them, how a SIGBUS error generates and how it is different from SIGSEGV which is more obviously occurs.

The reason of SIGSEGV and SIGBUS are:
Signal  Code                 Reason
SIGSEGV        
SEGV_MAPERR          address not mapped to object
SEGV_ACCERR          invalid permissions for mapped object
____________________________________________________________
SIGBUS
BUS_ADRALN           invalid address alignment
BUS_ADRERR           non-existent physical address
BUS_OBJERR           object specific hardware error

SIGBUS: signal number=10;
SIGSEGV: signal number=11;

Here is an sample program which will generate a SIGBUS error:

//file:sigbus.c
int main(int argc, char **argv)
{
    int testvar = 0x12345678;
    int *testvarp;

    testvarp = &testvar;
    printf("testvarp was %lx\n", testvarp);
    printf("testvar was %lx\n", *testvarp);

    testvarp = (int *)(((char *)testvarp) + 1);
    printf("testvarp is %lx\n", testvarp);
    printf("testvar is %lx\n", *testvarp);
 
} 
 
$gcc sigbus.c
devtest6:/home/jkongkon/sea>./a.out
testvarp was ffbef224
testvar was 12345678
testvarp is ffbef225
Bus Error 

devtest6:/home/jkongkon/sea>uname -a
SunOS devtest6 5.8 Generic_117350-39 sun4u sparc SUNW,Ultra-80
devtest6:/home/jkongkon/sea>

The above sample code illustrate how a SIGBUS got generated as a result of a
"invalid address alignment", with the error code BUS_ADRALN. This example
illustrates that a SIGBUS can generate as the result of a programming error.

Another reason where SIGBUS can generate is explained below:
You are currently using a external I/O device by mapping the device memory
mapping into the system memory (Memory mapped I/O). You have used it. And
now, you have disconnected it gracefully. But, somehow your code is trying
to use an previouslt used address still in your code. The result in this
case will be an SIGBUS, the reason is BUS_ADRERR, "non-existent physical
address".

I guess, everyone who does some system programming has got SIGSEGV at some
point. The simplest way to get a SIGSEGV is this:
main(){
int *p=(int*)0;
printf("*p=%d\n", *p);
}

Result="Segmentation Fault".

Here are some reasons why we get these signals:
SIGSEGV <-- Attempted write into a region mapped as read-only.
SIGBUS <-- Attempted access to    a portion of the buffer that does not 
correspond to the   associated  file(for example,    beyond the end of the 
file, including the case where   another process has truncated the file).    

-x The end x- 

No comments: