What is a segmentation fault? Is it different in C and C++? How are segmentation faults and dangling pointers related?
Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory – accessing a variable that has already been freed, writing to a read-only portion of the memory, etc. Segmentation fault is essentially the same in most languages that let you mess with memory management, there is no principal difference between segfaults in C and C++.
There are many ways to get a segfault, at least in the lower-level languages such as C(++). A common way to get a segfault is to dereference a null pointer:
int *p = NULL;
*p = 1;
Another segfault happens when you try to write to a portion of memory that was marked as read-only:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Dangling pointer points to a thing that does not exist anymore, like here:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
The pointer p dangles because it points to the character variable c that ceased to exist after the block ended. And when you try to dereference dangling pointer (like *p='A'), you would probably get a segfault.
It would be worth noting that segmentation fault isn't caused by directly accessing another process memory (this is what I'm hearing sometimes), as it is simply not possible. With virtual memory every process has its own virtual address space and there is no way to access another one using any value of pointer. Exception to this can be shared libraries which are same physical address space mapped to (possibly) different virtual addresses and kernel memory which is even mapped in the same way in every process (to avoid TLB flushing on syscall, I think). And things like shmat ;) - these are what I count as 'indirect' access. One can, however, check that they are usually located long way from process code and we are usually able to access them (this is why they are there, nevertheless accessing them in a improper way will produce segmentation fault).
Still, segmentation fault can occur in case of accessing our own (process) memory in improper way (for instance trying to write to non-writable space). But the most common reason for it is the access to the part of the virtual address space that is not mapped to physical one at all.
And all of this with respect to virtual memory systems.
A segmentation fault is caused by a request for a page that the process does not have listed in its descriptor table, or an invalid request for a page that it does have listed (e.g. a write request on a read-only page).
A dangling pointer is a pointer that may or may not point to a valid page, but does point to an "unexpected" segment of memory.
To be honest, as other posters have mentioned, Wikipedia has a very good article on this so have a look there. This type of error is very common and often called other things such as Access Violation or General Protection Fault.
They are no different in C, C++ or any other language that allows pointers. These kinds of errors are usually caused by pointers that are
Used before being properly initialised
Used after the memory they point to has been realloced or deleted.
Used in an indexed array where the index is outside of the array bounds. This is generally only when you're doing pointer math on traditional arrays or c-strings, not STL / Boost based collections (in C++.)
According to Wikipedia:
A segmentation fault occurs when a
program attempts to access a memory
location that it is not allowed to
access, or attempts to access a memory
location in a way that is not allowed
(for example, attempting to write to a
read-only location, or to overwrite
part of the operating system).
Segmentation fault is also caused by hardware failures, in this case the RAM memories. This is the less common cause, but if you don't find an error in your code, maybe a memtest could help you.
The solution in this case, change the RAM.
edit:
Here there is a reference: Segmentation fault by hardware
Wikipedia's Segmentation_fault page has a very nice description about it, just pointing out the causes and reasons. Have a look into the wiki for a detailed description.
In computing, a segmentation fault (often shortened to segfault) or access violation is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation.
The following are some typical causes of a segmentation fault:
Dereferencing NULL pointers – this is special-cased by memory management hardware
Attempting to access a nonexistent memory address (outside process's address space)
Attempting to access memory the program does not have rights to (such as kernel structures in process context)
Attempting to write read-only memory (such as code segment)
These in turn are often caused by programming errors that result in invalid memory access:
Dereferencing or assigning to an uninitialized pointer (wild pointer, which points to a random memory address)
Dereferencing or assigning to a freed pointer (dangling pointer, which points to memory that has been freed/deallocated/deleted)
A buffer overflow.
A stack overflow.
Attempting to execute a program that does not compile correctly. (Some compilers will output an executable file despite the presence of compile-time errors.)
Segmentation fault occurs when a process (running instance of a program) is trying to access read-only memory address or memory range which is being used by other process or access the non-existent (invalid) memory address.
Dangling Reference (pointer) problem means that trying to access an object or variable whose contents have already been deleted from memory, e.g:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
In simple words: segmentation fault is the operating system sending a signal to the program
saying that it has detected an illegal memory access and is prematurely terminating the program to prevent
memory from being corrupted.
There are several good explanations of "Segmentation fault" in the answers, but since with segmentation fault often there's a dump of the memory content, I wanted to share where the relationship between the "core dumped" part in Segmentation fault (core dumped) and memory comes from:
From about 1955 to 1975 - before semiconductor memory - the dominant technology in computer memory used tiny magnetic doughnuts strung on copper wires. The doughnuts were known as "ferrite cores" and main memory thus known as "core memory" or "core".
Taken from here.
"Segmentation fault" means that you tried to access memory that you do not have access to.
The first problem is with your arguments of main. The main function should be int main(int argc, char *argv[]), and you should check that argc is at least 2 before accessing argv[1].
Also, since you're passing in a float to printf (which, by the way, gets converted to a double when passing to printf), you should use the %f format specifier. The %s format specifier is for strings ('\0'-terminated character arrays).
Simple meaning of Segmentation fault is that you are trying to access some memory which doesn't belong to you. Segmentation fault occurs when we attempt to read and/or write tasks in a read only memory location or try to freed memory. In other words, we can explain this as some sort of memory corruption.
Below I mention common mistakes done by programmers that lead to Segmentation fault.
Use scanf() in wrong way(forgot to put &).
int num;
scanf("%d", num);// must use &num instead of num
Use pointers in wrong way.
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
Modifying a string literal(pointer try to write or modify a read only memory.)
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
Try to reach through an address which is already freed.
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
Stack Overflow -: Running out of memory on the stack
Accessing an array out of bounds'
Use wrong format specifiers when using printf() and scanf()'
Consider the following snippets of Code,
SNIPPET 1
int *number = NULL;
*number = 1;
SNIPPET 2
int *number = malloc(sizeof(int));
*number = 1;
I'd assume you know the meaning of the functions: malloc() and sizeof() if you are asking this question.
Now that that is settled,
SNIPPET 1 would throw a Segmentation Fault Error.
while SNIPPET 2 would not.
Here's why.
The first line of snippet one is creating a variable(*number) to store the address of some other variable but in this case it is initialized to NULL.
on the other hand,
The second line of snippet two is creating the same variable(*number) to store the address of some other and in this case it is given a memory address(because malloc() is a function in C/C++ that returns a memory address of the computer)
The point is you cannot put water inside a bowl that has not been bought OR a bowl that has been bought but has not been authorized for use by you.
When you try to do that, the computer is alerted and it throws a SegFault error.
You should only face this errors with languages that are close to low-level like C/C++. There is an abstraction in other High Level Languages that ensure you do not make this error.
It is also paramount to understand that Segmentation Fault is not language-specific.
There are enough definitions of segmentation fault, I would like to quote few examples which I came across while programming, which might seem like silly mistakes, but will waste a lot of time.
You can get a segmentation fault in below case while argument type mismatch in printf:
#include <stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
output : Segmentation Fault (SIGSEGV)
When you forgot to allocate memory to a pointer, but try to use it.
#include <stdio.h>
typedef struct{
int a;
} myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
output : Segmentation Fault (SIGSEGV)
In computing, a segmentation fault or access violation is a fault, or failure condition, raised by hardware with memory protection,
notifying an operating system the software has attempted to access a
restricted area of memory. -WIKIPEDIA
You might be accessing the computer memory with the wrong data type. Your case might be like the code below:
#include <stdio.h>
int main(int argc, char *argv[]) {
char A = 'asd';
puts(A);
return 0;
}
'asd' -> is a character chain rather than a single character char data type. So, storing it as a char causes the segmentation fault. Stocking some data at the wrong position.
Storing this string or character chain as a single char is trying to fit a square peg in a round hole.
Terminated due to signal: SEGMENTATION FAULT (11)
Segm. Fault is the same as trying to breath in under water, your lungs were not made for that. Reserving memory for an integer and then trying to operate it as another data type won't work at all.
Segmentation fault occurs when a process (running instance of a program) is trying to access a read-only memory address or memory range which is being used by another process or access the non-existent memory address.
seg fault,when type gets mismatched
A segmentation fault or access violation occurs when a program attempts to access a memory location that is not exist, or attempts to access a memory location in a way that is not allowed.
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Here i[1000] not exist, so segfault occurs.
Causes of segmentation fault:
it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
De-referencing NULL pointers – this is special-cased by memory management hardware.
Attempting to access a nonexistent memory address (outside process’s address space).
Attempting to access memory the program does not have rights to (such as kernel structures in process context).
Attempting to write read-only memory (such as code segment).
When I executed the following code:
AVFrame tmp = frames_video1[k]; //AVFrame frames_video1[]
AVFrame *avf1 = &tmp;
AVFrameSideData* avfsd1=NULL;
if(avf1->side_data != NULL)
printf("avf1->side_data is not NULL!!...........\n");
avfsd1 = av_frame_get_side_data(avf1, AV_FRAME_DATA_MOTION_VECTORS);
I came across segmentation fault happened at av_frame_get_side_data(avf1, AV_FRAME_DATA_MOTION_VECTORS):
avf1->side_data is not NULL!!...........
Segmentation fault (core dumped)
why?
here is the output of gdb:
(gdb) print avf1->side_data->type
Cannot access memory at address 0x0
(gdb) print frames_video1[1]->side_data->type
Cannot access memory at address 0x0
surprisingly, avf1 points to a corrupted frame whose side_data->type is null, which is abnormal. The cause of the issue resides somewhere else.
AVFrame tmp = frames_video1[k]; //AVFrame frames_video1[]
AVFrame *avf1 = &tmp;
You can't do this. I don't know where you learned this, but this is not allowed and fundamentally cannot work. You don't know the size of AVFrame in the application (it is not part of FFmpeg's ABI), so you cannot place a copy on the stack. Instead, do this:
AVFrame *avf1 = frames_video1[k];
Do not ever copy an FFmpeg object on the stack, it will not work. This also means frames_video1[] needs to be an array of AVFrame *, i.e. AVFrame pointers, not an array of AVFrame. If you don't understand why, read about pointers and memory in C and remember again that AVFrame's size is not part of the FFmpeg ABI.
Now, let's debug your object. First, basics of C stack: how many frames are in frames_video1[], and what is k? What is frames_video1[k]->data[0] or frames_video[k]->linesize[0]? Are they legal? Are you sure frames_video1[k] is a legal object? The fact that some copy of non-existing memory is non-NULL means nothing.
Secondly, if the object is legal, what is AVFrame->nb_side_data? You cannot access AVFrame->side_data[] beyond that index.
(gdb) print avf1->side_data->type
You can't do that either. side_data[] is an array of pointers, so instead do this:
(gdb) print avf1->side_data[0]->type
All that said, I again highly recommend you to read up on C pointers and memory allocation, I don't think you entirely understand it. FFmpeg is a very low-level C library and not understanding C will cause lots of grief.
I have run gdb, as my code show segfault. I understand that the code that give the error is
210 if (colour_s->colorlist.colorlist_id == 1)
(gdb) print colour_s
$1 = (car_colour_list_t_slot *) 0x21
(gdb) print colorlist
$2 = (car_colour_list_t *) 0x12d1a80
(gdb) print colour_s->colorlist
Cannot access memory at address 0x21
typedef struct {
int colorlist_id;
} car_colour_list_t;
typedef struct _car_colour_list_t_slot {
car_colour_list_t colorlist;
struct _car_colour_list_t_slot *next, *prev;
} car_colour_list_t_slot;
car_colour_list_t_slot *colour_s;
colour_s = (car_colour_list_t_slot *)malloc(sizeof(car_colour_list_t_slot));
car_colour_list_t *colorlist;
colorlist = (car_colour_list_t *)malloc(sizeof(car_colour_list_t));
I have already assigned those pointers memory, but when I tried to print colour_s->colorlist it fails (can not access memory at address 0x21)
Can anyone understand why this happens, although I have already assign memory to each poitner?
Thank you
The colour_s pointer is definitely invalid. There is no doubt about it. GDB is simply informing you of this fact. (Any pointer near 0x0 is invalid, and any pointer with a residue modulo 4 is invalid for your structure.) The malloc function will never return 0x21.
There are lots of ways your program can do this. They boil down to two basic types of errors in your program:
colour_s was not initialized.
colour_s was initialized, but it was accidentally overwritten by an error in a different part of your code.
there is an error in GDB or your compiler (not worth considering)
Run your program with Valgrind or set a watchpoint on colour_s. These will help you discover where the error is in your code.
As an alternative exercise, see if you can find the error just by reading your code, without running it. Read carefully. This kind of exercise will make you a better programmer.
I'm using a double-linked list and getting some odd performance regarding edge cases when we're dealing with previous or next pointers that are null. GDB returns the following error:
Program received signal SIGSEGV, Segmentation fault.
0x0804a9c1 in DLinkDelete (delete=0xd8c9d33c) at test.c:213
213 if (prevdl && prevdl->next)
(gdb) p prevdl
$39 = (DoubleLink *) 0xdadadada
(gdb) p prevdl->next
$40 = (void *) 0x0
DoubleLink is a struct with the following format:
typedef struct
{
void *next;
void *prev;
} DoubleLink;
Why would a segmentation fault be raised here?
Presumably prevdl points to invalid memory ? Come on, does 0xdadadada really look like a valid address to you ? "It's too idiotic to be schizophrenic".
the 0xdadadada address seems very weird although it is not NULL. Maybe you're trying to read a memory that is not allowed to you.
The value:
0xdadadada
looks suspiciously unlike a real pointer value. Just because a pointer is not NULL does not mean it is valid. And if you use an invalid pointer, you will get aseg fault, or whatever.
0xdadadada looks a bit suspicious, perhaps prevdl hasn't been properly initialised? Or maybe it's been stomped on by some other code.
Maybe you should try running the test under valgrind and see if it reports anything?
0xdadadada doesn't sound like a very likely value for a valid pointer... most likely a debugging initialiser.
Specifically, it means you're accessing data that hasn't been initialized at all. Question -- it this the first attempt to use this structure?
In any case, check your initialization code; when you create the node, I'd bet the very first node, which has no previous, you aren't setting its value, but in the code above you are trying to access it.
I am trying to debug a segfault, and I have this output from gdb:
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x08048af9 in parse_option_list (ptr=0x6f72505f <Address 0x6f72505f out of bounds>, box_name=0x696d6978 <Address 0x696d6978 out of bounds>, option_list=0x313a7974,
num_elements=0x33313532) at submit.c:125
125 memcpy(&(option_list[(*num_elements)].value), value, 24);
(gdb) p num_elements
$15 = (int *) 0x33313532
(gdb) p *num_elements
Cannot access memory at address 0x33313532
(gdb)
It looks to me like something in memcpy() is going haywire. But I can't figure out what exactly the problem is, since that line references so many variables.
Can somebody help figure out what the 0x8048af9 in parse_option_list... line is telling me?
My function signature is:
int parse_option_list(char *ptr, char *box_name,
struct option_list_values *option_list, int *num_elements)
And this might be useful:
struct option_list_values {
char value[24];
char name[24];
};
Also, the variables value and name are not segfaulting (but if you think they are, i can post the code which sets those values.) But right now, if I can understand this gdb output, I will be happy as a clam! Thank you!
You have all the signs of a classic buffer overflow. The values of all the stack parameters have been overwritten by ASCII text - here is the translation of those values (assuming you have a little-endian architecture, which looks right):
ptr = 0x6f72505f = "_Pro"
box_name = 0x696d6978 = "ximi"
option_list = 0x313a7974 = "ty:1"
num_elements = 0x33313532 = "2513"
Concatenating them together gives "_Proximity:12513" - if this substring looks familiar to you, you should be able to track down where that data is being copied around - somewhere you are copying it into an array stored on the stack, without proper bounds checking.
0x8048af9 is the instruction pointer - the address of the executable code in memory that your code was at when the SEGFAULT occurred.
Are you sure that option_list[(*num_elements)].value is a valid address? You might have a buffer overflow, and be overwriting something you shouldn't be.
If num_elements is the length of option_list, then option_list[(*num_elements)] refers to just after the end of the list.
ptr=0x6f72505f - Address 0x6f72505f out of bounds
This is the useful part in this case
The first input to parse_option_list is invalid. Possibly an uninitialized pointer.