Hello,

Due to prominent request, I have written a short tutorial to assist programmers debug errors in this vast subject. Let's begin with a brief introduction.

Introduction
Having wondered about these errors and why they occur without pre-warning continuously lead programmers to ask questions like “Why do I get this error?” or “What is this error?”. These questions can be answered.

The Truth Behind This Error
This indecisive error can be difficult to pinpoint, and can take unnecessary debug-time to locate.

Through this tutorial, we will explain what a segmentation fault is, how it is caused, and how it can be resolved. As previously stated, this error is indecisive and will take your know-how to detect it in your program.

The following list is provided to greater your understanding of the segmentation fault error:

  • A segmentation fault can be an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error.
  • A segmentation fault can be caused by memory misuse. Your program is attempting I/O on an area of memory it is not permitted to access. This can have many causes; some of the more common ones are "wild pointers" and buffer overflow (for example, allocating n characters for a buffer, and n+1 characters are written).
  • A segmentation fault (sometimes referred to as segfault for short) can be a particular error condition that can occur during the operation of computer software. In short, 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 it is not allowed to (e.g., attempts to write a read-only location).
  • A segmentation fault can be a type of error which occurs when you try to access a non-existent physical memory address.
  • A segmentation fault can occur if you freed memory and then within the scope of the same program try to re-use the same memory.
  • A segmentation fault, for software, can occur in case of hardware errors, for example the Hard Disc or Memory failure. To find out, try running memtest86 and/or any hard-disk diagnostic tools from the manufacturer.
  • A segmentation fault can be an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers in the source code, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.
  • A segmentation fault can occur when running a program that is reading or writing non-exist segment (physical memory space).
  • It can be a sporadic occurrence.

A Closer Look
With this information in mind, it may be easier to detect where a segmentation fault can occur. If we look at the following code, we can see that it looks a bit ambiguous. Does it fail when executed and display the Segmentation Fault message? It should, in most cases:

Example 1.1
Code:
#include <string.h>

int main() {
	memset((char *)0x0, 42, 200);

	return 0;
}
This is quite obvious as we try to fill the buffer 0x00. As we know 0x00 is 0 or NULL in the C/C++ language. This tells us we are requesting our program to write to memory that isn’t ours, that doesn’t exist, and that is simply nil. This is a perfect example of a Segmentation Fault. See Bulleted List #4 for greater detail.

Next are some examples that cause segmentation faults or memory violations.

Example 1.2
Code:
int main() {
	char *abc;
	abc[0] = 'z';

	return 0;
}
This causes a violation because we are trying to modify abc, which at this point contains a non-valid address. Remember, abc is a pointer. Remember, a pointer is a variable containing the address of another variable. This program crashes because we are trying to write to memory that isn't ours. Like regular variables, un-initialized pointers will not cause a compiler error, but using an un-initialized pointer could result in unpredictable and potentially disastrous outcomes.

In other cases, there are string literals and constants. Our following example will show that abc is a pointer that is initialized to contain the read-only address of a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you attempt to modify the strings contents.

Example 1.3
Code:
int main() {
	char *abc = "Hello";

	return 0;
}
This program, however, does not crash. It will only result in a crash if we try to change the contents of the string. This is similar to the const qualifier. The first rule of the const qualifier is this: A constant must be initialized, it is not possible to give it a value anywhere else. Keep in mind, the compiler does not give a warning if a pointer is unsafe/un-permitted to modify its contents.

In our next example, you will see that trying to access or modify an array index that is out-of-bounds will also generate a segmentation fault.

Example 1.4
Code:
int main() {
	char abc[6] = "Hello";
	abc[6] = '!';

	return 0;
}
We know in C++ an array is a concrete data structure, which can be used to implement the Array or Vector data type (though other implementations are possible).

C++ arrays have the following properties:
  • All elements in the array are of the same type
  • Elements are accessed by their index, starting at 0
  • The array has a fixed capacity, which must be known at compile time

The fixed capacity of an array means that it cannot be increased or decreased once the array has been created.

Array subscripts always start at zero in C, so the elements are abc[0], abc[1], …, abc[5]. Simply, counting 6 numbers starting and including 0 produces 5.

Moving from simple examples, let’s view pointers to classes and pointers to structures. We know that until a pointer holds the address of a variable, it isn’t useful. Generally, pointers can be allocated using new/delete in C++, malloc() and free() in C, given the address of another object, or even take on a literal or a constant value/string. Some issues are that we create a pointer to a class and expect it to work. For structures/classes, the “.” operator connects the structure/class name and the member name. Pointers to structures/classes, on the other hand, use an alternative notation as a shorthand, using the operator “->”. Both of these operators read left to right. When dealing with pointers to structures/classes, the “->” operator will be used.

Example 1.5
Code:
struct Foo {
	int n;
};

int main() {
	Foo *foo;
	
	foo->n = 4;

	return 0;
}
A segmentation fault will occur when Example 1.4 is compiled and executed. The pointer foo to Foo contains no valid object or address, thus will result in a crash.

Pointers, above all other variables, express computations better than others and are sometimes the only way. The flexibility of pointers can be dangerous. Memory is key when running a machine or a program. Learning how to handle memory in the C/C++ language is advantageous. This tutorial is a guide to exploring segmentation faults and why they occur. The best way to fix a segmentation fault is to learn how to handle memory, allocating and freeing, properly. There are many tutorials on how to allocate memory, pass object memory, and share memory in the other FAQ tutorials.

Finding The Error
On another note, detecting a segmentation fault can be difficult if you make it. A good tool is to look. Look for any pointers that may be un-initialized, modified as a literal or constant, de-referenced while a NULL value, or accessing memory that isn’t yours.

Segmentation faults/violations are typically out-of-bounds array references and/or references through un-initialized or mangled pointers. Look very closely in your program for bizarre things like that. Common examples are:

Example 2.1(a) [C Example]
Code:
#include <stdio.h>

int main() {
	int c;
	scanf("%d", c);

	return 0;
}
Example 2.1(b) [C++ Example]
Code:
#include <iostream>
using namespace std;

int main() {
	int* p = new int[100];
	cout << p[100];
	delete []p;

	return 0;
}
C Example: This isn’t good practice, and may crash because scanf()’s arguments must be pointers. If you want to store the result of a scanf() operation on a standard variable you should precede it with the reference operator, i.e. an ampersand sign (&).

C++ Example: 100 spots were allocated. From 0 to 99. Modifying the 100'th index will cause a crash because it does not exist. It is an invalid subscript.

Example 2.2(a) [C Example]
Code:
#include <stdio.h>

int main() {
	int c;
	scanf("%d", &c);

	return 0;
}
Example 2.2(b) [C++ Example]
Code:
#include <iostream>
using namespace std;

int main() {
	int* p = new int[100];
	cout << p[99];
	delete []p;

	return 0;
}
(Remember array subscripts in C and C++ start with 0)

Conclusion
There are a number of methods for finding out where the program went out of bounds. One method is to use printf(), cout, or any other means of printing, to print statements and determine how far the program runs before it crashes, and to print out the contents of interesting variables.

On a last note, if you run into a “Segmentation Error” it usually means the same as a “Segmentation Fault” or “Segmentation Violation”; which all comes down to where it generally means that your program tried to access memory it shouldn't have, invariably as a result of stack corruption or improper pointer use.