Definitive List of Common Reasons for Segmentation Faults
NOTE: We have a lot of segfault questions, with largely the same answers, so I'm trying to collapse them into a canonical question like we have for undefined reference.
Although we have a question covering what a segmentation fault is, it covers the what , but doesn't list many reasons. The top answer says "there are many reasons", and only lists one, and most of the other answers don't list any reasons.
All in all, I believe we need a well-organized community wiki on this topic, which lists all the common causes (and then some) to get segfaults. The purpose is to aid in debugging, as mentioned in the answer's disclaimer.
I know what a segmentation fault is, but it can be hard to spot in the code without knowing what they often look like. Although there are, no doubt, far too many to list exhaustively, what are the most common causes of segmentation faults in C and C++?
WARNING!
The following are potential reasons for a segmentation fault. It is virtually impossible to list all reasons . The purpose of this list is to help diagnose an existing segfault.
The relationship between segmentation faults and undefined behavior cannot be stressed enough! All of the below situations that can create a segmentation fault are technically undefined behavior. That means that they can do anything, not just segfault -- as someone once said on USENET, "it is legal for the compiler to make demons fly out of your nose.". Don't count on a segfault happening whenever you have undefined behavior. You should learn which undefined behaviors exist in C and/or C++, and avoid writing code that has them!
More information on Undefined Behavior:
What Is a Segfault?
In short, a segmentation fault is caused when the code attempts to access memory that it doesn't have permission to access . Every program is given a piece of memory (RAM) to work with, and for security reasons, it is only allowed to access memory in that chunk.
For a more thorough technical explanation about what a segmentation fault is, see What is a segmentation fault?.
Here are the most common reasons for a segmentation fault error. Again, these should be used in diagnosing an existing segfault . To learn how to avoid them, learn your language's undefined behaviors.
This list is also no replacement for doing your own debugging work . (See that section at the bottom of the answer.) These are things you can look for, but your debugging tools are the only reliable way to zero in on the problem.
Accessing a NULL or uninitialized pointer
If you have a pointer that is NULL ( ptr=0
) or that is completely uninitialized (it isn't set to anything at all yet), attempting to access or modify using that pointer has undefined behavior.
int* ptr = 0;
*ptr += 5;
Since a failed allocation (such as with malloc
or new
) will return a null pointer, you should always check that your pointer is not NULL before working with it.
Note also that even reading values (without dereferencing) of uninitialized pointers (and variables in general) is undefined behavior.
Sometimes this access of an undefined pointer can be quite subtle, such as in trying to interpret such a pointer as a string in a C print statement.
char* ptr;
sprintf(id, "%s", ptr);
See also:
Accessing a dangling pointer
If you use malloc
or new
to allocate memory, and then later free
or delete
that memory through pointer, that pointer is now considered a dangling pointer . Dereferencing it (as well as simply reading its value - granted you didn't assign some new value to it such as NULL) is undefined behavior, and can result in segmentation fault.
Something* ptr = new Something(123, 456);
delete ptr;
std::cout << ptr->foo << std::endl;
See also:
Stack overflow
[No, not the site you're on now, what is was named for.] Oversimplified, the "stack" is like that spike you stick your order paper on in some diners. This problem can occur when you put too many orders on that spike, so to speak. In the computer, any variable that is not dynamically allocated and any command that has yet to be processed by the CPU, goes on the stack.
One cause of this might be deep or infinite recursion, such as when a function calls itself with no way to stop. Because that stack has overflowed, the order papers start "falling off" and taking up other space not meant for them. Thus, we can get a segmentation fault. Another cause might be the attempt to initialize a very large array: it's only a single order, but one that is already large enough by itself.
int stupidFunction(int n)
{
return stupidFunction(n);
}
Another cause of a stack overflow would be having too many (non-dynamically allocated) variables at once.
int stupidArray[600851475143];
One case of a stack overflow in the wild came from a simple omission of a return
statement in a conditional intended to prevent infinite recursion in a function. The moral of that story, always ensure your error checks work!
See also:
Wild pointers
Creating a pointer to some random location in memory is like playing Russian roulette with your code - you could easily miss and create a pointer to a location you don't have access rights to.
int n = 123;
int* ptr = (&n + 0xDEADBEEF); //This is just stupid, people.
As a general rule, don't create pointers to literal memory locations. Even if they work one time, the next time they might not. You can't predict where your program's memory will be at any given execution.
See also:
Attempting to read past the end of an array
An array is a contiguous region of memory, where each successive element is located at the next address in memory. However, most arrays don't have an innate sense of how large they are, or what the last element is. Thus, it is easy to blow past the end of the array and never know it, especially if you're using pointer arithmetic.
If you read past the end of the array, you may wind up going into memory that is uninitialized or belongs to something else. This is technically undefined behavior . A segfault is just one of those many potential undefined behaviors. [Frankly, if you get a segfault here, you're lucky. Others are harder to diagnose.]
// like most UB, this code is a total crapshoot.
int arr[3] {5, 151, 478};
int i = 0;
while(arr[i] != 16)
{
std::cout << arr[i] << std::endl;
i++;
}
Or the frequently seen one using for
with <=
instead of <
(reads 1 byte too much):
char arr[10];
for (int i = 0; i<=10; i++)
{
std::cout << arr[i] << std::endl;
}
Or even an unlucky typo which compiles fine (seen here) and allocates only 1 element initialized with dim
instead of dim
elements.
int* my_array = new int(dim);
Additionally it should be noted that you are not even allowed to create (not to mention dereferencing) a pointer which points outside the array (you can create such pointer only if it points to an element within the array, or one past the end). Otherwise, you are triggering undefined behaviour.
See also:
Forgetting a NUL terminator on a C string.
C strings are, themselves, arrays with some additional behaviors. They must be null terminated, meaning they have an