Meaning of Segmentation Fault
Before jumping on to the actual scenarios, lets quickly discuss what does Segmentation Fault means?
A segmentation fault occurs mainly when our code tries to access some memory location which it is not suppose to access.
For example :
- Working on a dangling pointer.
- Writing past the allocated area on heap.
- Operating on an array without boundary checks.
- Freeing a memory twice.
- Working on Returned address of a local variable
- Running out of memory(stack or heap)
Examples of Segmentation Fault in C
1) Working on a dangling pointer.
Well, before discussing this scenario of segmentation fault, lets understand what is dangling pointers. A pointer which holds memory address of a memory which is already freed is known as a dangling pointer. You cannot figure out whether a given pointer is dangling or not until you use it. When a dangling pointer is used, usually a segmentation fault is observed.
Now, lets look at a code to understand it :
Code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
char *p = malloc(3);
*p = 'a';
*(p+1) = 'b';
*(p+2) = 'c';
free(p);
*p = 'a';
return 0;
}
Lets take another example :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char *p ;
strcat(p, "abc");
printf("\n %s \n", p);
return 0;
}
A yet another example could be :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void func(char ** argv)
{
char arr[2];
strcpy(arr, argv[1]);
return;
}
int main(int argc, char *argv[])
{
func(argv);
return 0;
}
2)Writing past the allocated area on heap.
There are times when a logic inadvertently writes past the allocated area on heap. This may happen while performing some operations in a loop or not doing array bound checks etc. So this type of situation also results in a segmentation fault. For example, look at the following code :
Code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
char *p = malloc(3);
int i = 0;
for(i=0;i<0Xffffffff;i++)
{
p[i] = 'a';
}
printf("\n %s \n", p);
return 0;
}
3) Operating on an array without boundary checks.
In this scenario, the logic is flawed in a way that an array is written out of its boundary limits and in a rare scenario (or in case of exploits), this buffer overflow may result in overwriting the return address(ie the address to return after executing the present function). And hence returning on a garbage address and executing the instruction kept there may very well cause segmentation fault.
Lets look the following code :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void func(char ** argv)
{
char arr[2];
strcpy(arr, argv[1]);
return;
}
int main(int argc, char *argv[])
{
func(argv);
return 0;
}
Here is the output of the code above(I tried to run it twice with different command line args) :
Code:
~/practice $ ./segfault abc ~/practice $
Code:
~/practice $ ./segfault abcjflcnmscn,snlkewfdebddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd Segmentation fault
4) Freeing a memory twice.
This is a bit specific to function free() but is a very common reason for segmentation faults to occur. The specification of free() specifies that if this function is used again on an already freed pointer, the results are undefined and mostly we see a segmentation fault in this scenario.
Lets quickly see the code :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[])
{
char *p = malloc(8);
free(p);
free(p);
return 0;
}
5) Working on Returned address of a local variable
I this scenario, the address of a local variable is returned to calling function and this address is used there. For example, consider the following code :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* func()
{
char c = 'a';
return &c;
}
int main(int argc, char *argv[])
{
char *ptr = func();
char arr[10];
memset(arr,'0', sizeof(arr));
arr[0] = *ptr;
return 0;
}
6) Running out of memory.
It may happen that we run out of memory. This memory can be a stack memory or a heap memory. Lets consider the following two examples to understand this :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
main();
}
Consider example of heap memory :
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
unsigned int i = 0;
for(i=0; i< 0xFFFFFFFF;i++);
char *p = malloc(100);
return 0;
}
Conclusion
To conclude, in this article we studied the different ways in which one could screw up his/her program and get segmentation fault. This article should act as a good resource for those who are getting this error but not able to understand the reason.
Stay tuned for more!!!
No comments:
Post a Comment