The dreaded SIGSEGV !

Segmentation Fault or SIGSEGV is a dreaded error of most C programmers. It mostly occurs due to invalid access of memory. Most of the times the invalid memory access is a mistake. However recently one of my friend asked me a question (who was asked the same in an interview) as to what happened if an arbitrary address is accessed?

The question was as follows:

#include <stdio.h>
int main(int argc, char *argv[])
{
    int *p;
    p = (int*)1;
    printf("%d  %d", p, *p);
    return 0;
}

Now I had never come across a scenario where you assign a value directly to a pointer variable and my first thought was, would this even compile? As a matter of fact it did, when I did compile with gcc. But on running the output file, I got the dreaded Segmentation Fault.

Now curious as to why, I stepped through the code using gdb and this is what I stumbled upon:

breakpoint 1, main () at test.c:6
6 p = (int*)1;
(gdb) p p
$1 = (int *) 0x0
(gdb) n
7 printf("%d %d", p, *p);
(gdb) p p
$2 = (int *) 0x1
(gdb) p *p
Cannot access memory at address 0x1
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x00000000004004ac in main () at test.c:7
7 printf("%d %d", p, *p);

Now let’s dissect what exactly is going on. Variable is a pointer variable, means it can hold an address. Since its an integer pointer, p can hold address of an integer variable. Now when we assign (int*)1 to p, what is happening is 1 is being assigned to p. But 1 is not being assigned directly, since 1 is prefixed with (int*) which is essentially casting 1 as an address of an integer variable. Hence p is being assigned an address 0x01 which is a valid instruction! Now in all probability, 0x01 is a valid address, but most definitely not a valid address for the program we are running. (We know the OS and other programs are already running, so we can be certain some other process is running at the first memory location, which is a valid address, but not valid for our program to access!) Hence on trying to print the value at this address, we encounter Segmentation Fault!

Data Alignment and Padding

Usually we use structures in C to combine data relevant to an object or a problem. If we intend to create many objects of this structure, we have an array of structures. But how are these structures stored in memory? Let’s take a simple structure defined as below

struct abc
{
    int i;
    char c;
};

Now assuming a 32 bit architecture, we know an integer occupies 4 bytes and a char occupies 1 byte. So the instantaneous answer as to what is the size of struct abc would be 5. But the actual size occupied by a variable of the above struct is 8. This is because of the concept of Padding.

http://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/

The above link provides an excellent reference of how the memory is organized in today’s computers. We can see that memory is usually divided into four banks, each of 1 byte width. It so happens that the CPU can access all the four banks of 1 byte each in a single read instruction cycle which is the case with modern CPU architectures. So reading 4 bytes of data needs a single instruction and not four. In a 64 bit architecture, the CPU is capable of reading 8 bytes in a single instruction!

So, we learn that the CPU architecture decides how many bytes can be read at a time and this is referred as word length, which is 4 bytes or 8 bytes depending on the architecture. Let’s stick to 32 bit architecture or 4 byte word length for the rest of the article.

Now it does not mean that the CPU is not capable of reading one byte at a time. Just that reading one byte and four bytes would require equal CPU processing. Hence if we have a char and an int in a structure, the compiler would pad 3 bytes after the char. This is called Data Alignment.

So as a general rule of thumb, the starting address of a variable would depend on its type. A char can start at any address. However, a short, int, long, float or double will start at even memory addresses. Further, short will start at addresses divisible by 2, int and float would start at addresses divisible by 4, long and double would begin at addresses divisible by 8. Confused? Have a look at the diagram in the above link to clear things up.

So let’s consider the following structure.

struct xyz
{
    double a;    
    int b;
    double c;
};

Now would the size of the above structure be 20 bytes (8+4+8) ? Nope! It would be 24 bytes! This is because apart from word alignment, the compiler follows a natural alignment for the structure. It means that the padding is with respect to the largest data member of the structure. Hence there would be a 4 byte padding after variable b in the above structure. But why is this required? Now let’s say we have an array of the above structure and for simplicity, the start of address is 1000. If it were to occupy 20 bytes, then second element of the address would begin at address 1021, which is not a multiple of 8. So padding 4 bytes after b will begin the second element of the array at 1024 which is a multiple of 8. But why, you ask! This is because the emphasis is on performance. Since the cost of physical memory has reduced over time, the compiler would rather waste 4 bytes and ensure the CPU can read the next variable of the array quickly than to save 4 bytes. So in the above case, if the padding has happened, assuming the memory bank model mentioned in the above link, the CPU has to read every 7th memory bank when the structure array is accessed by index, which means it has to skip an even number of memory rows, which is more efficient for the CPU!

References:

http://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/

http://www.catb.org/esr/structure-packing/

Casting: Up or Down?

C++ Classes provide the convenience of Inheritance to help authors re-use existing code and make applications extensible. The class which does not derive at all is called the Base (or Parent) class and the class which derives from another class is called a Derived (or Child) class. The Inheritance causes an is-a relationship between the base and derived class. Say for example,

class Shape
{
.....
};
class Circle : public Shape
{
.....
};
class Triangle : public Shape
{
.....
};

Classes Circle and Triangle is-a Shape. Now what would happen if we start assigning their objects to each other. Lets find out. It would be wrong to assign a Triangle object to Circle and vice-versa. Though both are derived from Shape class, they both have unique properties which cannot be mix and matched. Now a Circle or Triangle object can be assigned to Shape class. A Circle or Triangle is a Shape, but apart from being a Shape, they have their own unique properties. This process of assigning a derived object to base type is called UpCasting. Since the Shape class doesn’t have the specific properties of Triangle or Circle, the derived object is said to be Sliced. This is referred to as object slicing. If the objects are of pointer type and the member functions are virtual, then appropriate functions are called at run time because to late binding. If the member functions are not virtual, the binding happens are compile time and expected results may not be seen. The opposite of UpCasting is DownCasting. It means, assigning the base class object to a derived type. Now a shape object can draw or resize, but need not necessarily have a radius (ex. Circle) or have three sides (ex. Triangle). We do know that the derived class has a few unique properties and methods not present in the base class. Hence a simple cast of base type to derived type is not possible. Hence such a cast should use the dynamic_cast conversion to achieve this. Dynamic cast evaluates the object being cast to the destination object and determines if it is a safe conversion. It returns an object of resultant type if it is safe or 0 if unsafe.

Reference: http://www.bogotobogo.com/cplusplus/upcasting_downcasting.php