Expert C Programming

(Jeff_L) #1

or address 32768, but not at address 1006 (since it is not exactly divisible by 8). Page and cache sizes
are carefully designed so that keeping the alignment rule will ensure that no atomic data item spills
over a page or cache block boundary.


The requirement for data to be stored aligned always reminds us of the kids' game of walking down a
sidewalk without placing a foot on a crack in the paving stones. "Step on a crack, break your mother 's
back" has mutated to "dereference nonaligned then cuss, cause an error on the bus." Maybe it's
Freudian or something; Mother was frightened by a Fortran I/O channel at an impressionable age. A
small program that will cause a bus error is:


union { char a[10];


int i;


} u;


int p= (int) &(u.a[1]);


p = 17; / the misaligned addr in p causes a bus error! */


This causes a bus error because the array/int union ensures that character array "a" is also at a
reasonably aligned address for an integer, so "a+1" is definitely not. We then try to store 4 bytes into
an address that is aligned only for single-byte access. A good compiler will warn about misalignment,
but it cannot spot all occurrences.


The compilers automatically allocate and pad data (in memory) to achieve alignment. Of course, there
is no such alignment requirement on disk or tape, so programmers can remain blissfully unaware of
alignment—until they cast a char pointer to an int pointer, leading to mysterious bus errors. A few
years ago bus errors were also generated if a memory parity error was detected. These days memory
chips are so reliable, and so well protected by error detection and correction circuitry, that parity
errors are almost unheard of at the application programming level. A bus error can also be generated
by referencing memory that does not physically exist; you probably won't be able to screw up this
badly without help from a naughty device driver.


Segmentation Fault


The segmentation fault or violation should already be clear, given the segment model explained earlier.
On Sun hardware, segmentation faults are generated by an exception in the memory management unit
(the hardware responsible for supporting virtual memory). The usual cause is dereferencing (looking
at the contents of the address contained in) a pointer with an uninitialized or illegal value. The pointer
causes a memory reference to a segment that is not part of your address space, and the operating
system steps in. A small program that will cause a segmentation fault is:


int *p=0;


p = 17; / causes a segmentation fault */


One subtlety is that it is usually a different programmatic error that led to the pointer having an invalid
value. Unlike a bus error, a segmentation fault will therefore be the indirect symptom rather than the
cause of the fault.


A worse subtlety is that if the value in the uninitialized pointer happens to be misaligned for the size
of data being accessed, it will cause a bus error fault, not a segmentation violation. This is true for
most architectures because the CPU sees the address before sending it to the MMU.

Free download pdf