On Mon, 29 Sep 2003, Vijay Kumar R Zanvar wrote:

> Hi,
>     I have following 2 questions:
>
>     * What is bus error?
>     * How is it different from segmentation fault?

Both are off topic for comp.lang.c so I'm replying privately. They are
more about the architecture and implementation you are using then C
language itself.

Question #1:

For a microprocessor (CPU, GPP, etc.) there are pins connecting the chip
to memory. This colletion of pins is called the BUS. There is a data bus
and an address bus. To reduce the number of pins on a chip, some
manufacturers will skip having an A0 pin. This means the last bit in the
address is assumed to always be zero. Or in other words, all addresses
must be even, e.g. 0, 2, 4, 6, 8, 10, etc. Some manufacturers drop pins A0
and A1. Thus addresses need to be a multiple of four, e.g. 0, 4, 8, 12,
16, 20, etc. If I wanted to address memory location 1 the compiler will
actually fetch 2 bytes from memory loction 0 then shift everything so I
only have the data from memory location 1. It does this without you, a C
programmer, ever knowing. So I write:

char array[10];
int i;

for(i = 0; i < sizeof array; i++) {
array[i] = i;
}

but the compiler will optimize it. It will store 0, 1 into memory location
0, it will store 2, 3 in memory location 2, etc. It will physically be
doing:

for(i = 0; i < sizeof array; i += 2) {
/* store the value of array[i] and array[i+1]
* in one pass.
*/
}

The compiler knows to do this 'trick' because we are using char. There are
ways of messing up the compiler. Simplest way:

char array[10];
int *p = (int *)1;
*p = 0; /* bus error */
or
p = &array[1]; /* odd address */
*p = 0; /* bus error */

The compiler understands that p is a pointer to int. It therefore assumes
it does not need the special 'trick'. It assumes p will always hold an
even address. By assigning p an odd address we confuse the compiler and it
creates a bus error. Another more subtle way is:

int i = 1;
scanf("%d", i); /* should have been scanf("%d", &i); */

we tell scanf we are passing the address of an integer. Instead we pass
the VALUE of the integer. The scanf function will assume 1, the value of
i, is a valid address. A bus error will occur.

NOTE: Only on machines with no A0 pin will a bus error occur.

Question #2:

Some compilers and/or operating systems create blocks of memory they call
segments for a program. The code will go in one segment, auto variables
will go in another segment, maybe local variables will go in a different
segment, dynamically allocated memory will be another segment, etc. The
options as to what constitutes a segment is different from compiler to
compiler. In some cases it might decide some segments are RAM, some are
ROM (Read Only Memory), some are NONE (no read or write). If you try
writing to a ROM you are going to get a segmentation fault. If you try
writing to NONE you are going to get a segmentation fault.

For example, string literals might be in ROM. So this will cause a
segementation fault:

char *s = "string literal";
s[0] = 'S'; /* segmentation fault */

The string might exist in ROM. So when I attempt to use s[0] = 'S'; I am
attempting to WRITE to ROM and I get a segmentation fault. Additionally,
this will segmentation fault:

#include <ctype.h>
#include <stdio.h>

int main(void)
{
char *c = (char *)0;
while(1) {
if(isprint(*c))
putchar(*c);
else
putchar('\n');
c++;
}

return 0;
}

Sooner of later this is going to attempt to read from NONE memory and
segmentation fault. On most machines it will segmentation fault on the
first read because memory location 0 is NONE to all but system tasks.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vice.president@whitehouse.gov