Segmentation Fault : behind the code

Segmentation fault
Segmentation fault (core dumped)

Did you just look at your laptop and said, "This is it buddy, don't check my patience, you are going to get hurt !!!".

If you are in this situation, then just try to understand the concept behind segmentation fault and forget the headache ;-)

Segmentation fault is the exception which occurs when a program tries to access an invalid memory. 
In simple words, it means accessing a memory which does not belong to you or you do not have authorization to access it. 

To resolve this, you must know about GNU Debugger(GDB), but if you are SHORT OF TIME then first try following example:

1  #include<stdio.h>
2  int main()
3  {
4   int *p;
5   *p= 7;
6   printf("Output = %d\n",*p);
7  }

 If we run this program, we will get Segmentation fault:

user@gene-laptop:~$ gcc -g segment.c
user@gene-laptop:~$ ./a.out
Segmentation fault (core dumped)

The -g option in gcc is used so that later this program can be debugged using GDB."If you don't know about GDB, just get along and follow the steps :)"

Now, debug your program as

user@gene-laptop:~$ gdb ./a.out
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/user/a.out...done.
(gdb) run
Starting program: /home/user/a.out 

Program received signal SIGSEGV, Segmentation fault.

0x080483f1 in main () at segment.c:5
5 *p=7;
(gdb) 

This means that we are trying to access an invalid memory at line 5. How??
It's because the pointer variable 'p' doesn't point to a memory location and when we are trying to write to this location. Verify it :

(gdb) print p
$1 = 0x0

So, its showing that the value of 'p' is NULL. To solve this, you should assign a memory location to this pointer variable.

1 #include<stdio.h>
2 int main()
3  {
4   int *p;
5   int a=0;
6   p = &a;  // Now the pointer is pointing to a valid memory location
7   *p=7;
8   printf("Output = %d\n",*p);
9  }

user@gene-laptop:~$ gcc -g segment.c
user@gene-laptop:~$ ./a.out
Output = 7

Explore some more examples : 

To understand this concept more deeply, first you should thoroughly understand GDB. Read it from here :
GNU Debugger (GDB) 

After that, look at some more examples below and try to follow the reason of segmentation fault :


example #1 :

1   #include<stdio.h>
2   const int i=5;
3   int main()
4   {
5     int*p;
6     p=&i;
7     *p=8;
8     printf("%d\n",*p);
9   }

 In the above program, we are trying to write to restricted(read-only constant integer) memory location.

example #2 :

1   #include<stdio.h>
2   #include<string.h>
3   int main()
4   {
5     char *str1 = "system";
6     char *str2 = "genes";
7     strcpy(str1,str2);
8     printf("%s %s\n",str1, str2);
9     return 0;
10  }

In this program, str1 is just a pointer(character type) which is not pointing to any valid memory location. So when we try to copy the contents of str2 and attempt to write that to an invalid memory location, Segmentation fault occurs. As a warning, we should not even store a string directly to a pointer variable(line 5 and 6).

user@gene-laptop:~$ gdb ./a.out
.
.
(gdb) run
Starting program: /home/user/a.out 

Program received signal SIGSEGV, Segmentation fault.

0xb7ea4ff2 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) backtrace
#0  0xb7ea4ff2 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1  0x08048441 in main () at segment.c:7
.
.
As our only interest is to find out that where our program crashed i.e in main() function. So we further check out details of frame 1.
.
.
(gdb) frame 1
#1  0x08048441 in main () at segment.c:7
7    strcpy(str1,str2);


example #3:

1  #include<stdio.h>
2  int main()
3  {
4   char ch;
5   FILE *fp;
6   fp=fopen("user.txt", "r");
7   while((ch = getc(fp))!=-1)
8   printf("%c", ch);
9   fclose(fp);
10  return 0;
11 }


Run this program:

user@gene-laptop:~$ gcc -g test.c
user@gene-laptop:~$ ./a.out
Segmentation fault (core dumped)
user@gene-laptop:~$ gdb ./a.out
.
.
.
(gdb) run
Starting program: /home/user/a.out

Program received signal SIGSEGV, Segmentation fault.
0xb7e886de in getc () from /lib/i386-linux-gnu/libc.so.6
(gdb) backtrace
#0  0xb7e886de in getc () from /lib/i386-linux-gnu/libc.so.6
#1  0x080484d2 in main () at test.c:7
(gdb) frame 1
#1  0x080484d2 in main () at test.c:7
7                  while((ch = getc(fp))!=-1)
.
Now ,check the value of file pointer fp and you will find out that 'fp' is NULL.
.
(gdb) print fp
$1 = (FILE *) 0x0
(gdb)

In this scenario, there is no logical error. It's just a case you may encounter. Here, the culprit is fopen() function. If the file "user.txt" is not present in the concerned directory, then getc() function will give segmentation fault as it will not know from where to fetch the data. So, it is advisable to check the return value of fopen() like functions(malloc, calloc etc).

-----------------------------------------------------------------------------------------------------------
If this article helped you, please like it. If you find anything wrong or confusing, please give your suggestions :-)

Comments

Popular posts from this blog

error: stray '\' in program

error: invalid application of ‘sizeof’ to incomplete type ‘struct ’

Expandable Arrays in C : behind the code