Locating A Segmentation Fault

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:

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.

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:

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.

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.

Segmentation Fault: I am 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, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

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.

I hope you don't mind replies to this topic.

Another option to find memory leaks and locate invalid memory access is the use of tools like Valgrind. Valgrind has an addresscheck tool that allows you to track access to invalid memory locations, even those that do not neccessarly lead to a segmentation fault.
Maybe some other people could list similar windows tools, I don't have any experience there :/

Thanks for the information about the tool, Valgrind. I've never heard of it before. I'll install it on my Red Hat system and give it a go.

- Stack Overflow

Segmentation Fault: I am 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, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

One way I find segfaults (damn them!) is to use the gdb debugger.
I use gcc as a compiler, so it may be different on other compilers. Compile your program with the -g option, the run the command gdb yourprog.
example

Code:

gcc -o myprog program.c -g
gdb myprog

In gdb, type the command run... It should tell you that your program had a segfault, and maybe what line it is around.
then typing bt (backtrace) will show you the last things your program did or tried to do... with any good line numbers.
That should give you a good lead on where to start looking for mistakes.

I think the main purpose of the OP was to explain how without the help of anything other than your C compiler, you can locate your own segfaults. Not everyone has a debugger or something like electric fence to hunt them down for them. However, by sprinkling printf statements through your code, you can usually hunt them down yourself without too much trouble.

One thing you might want to add however, is that you may want to be sure and flush the output stream to be sure what you're printing does in fact show up.

It seems to me the longer you program the more in tune you get with which line of code you made a little mistake. I'd say more than 75% of the time when I get a seg fault I know exactly what it was that broke.

>However, by sprinkling printf statements through your code, you can usually hunt them down yourself without too much trouble

Maybe I just think debuggers are cheating, but more often than not I'll do the prinf technique. Though, printf can also cause seg faults too

I thank everyone for their comments on Segmentation Faults. My short tutorial was to express the error, and how it's caused in great detail.

For those of you that do have a debugger, use it. It may save you time by using gdb, Valgrind, or any other debugger you may have.

My intention was to help those that don't have access to a debugger. A lot of new-comers get frustrated when they can't resolve a segmentation fault, and I'm hoping this guide can help them through it.

If they happen upon a debugger, I'm sure Rouss's post can help them use gdb if they have it, and/or Nyda's post if they are looking for an open-source tool.

Of course Quzah has a valid point. Flush the output stream if using printf() before the segmentation fault occurs, so it shows up.

- Stack Overflow

Segmentation Fault: I am 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, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

Another tip
Create an input file and then redirect input to that file.
Example lets say the program asks your name age and gender. Then the input file may look like:

Code:

Thantos
24
male

To redirect standard input use the < character as such:

Code:

program-name < file-name

example:

Code:

./hello < world.txt

This helps you in a few ways:
1) You have a set input which means you should get a set output
2) Time: It can read from the file faster then you can type
3) Allows you to focus on the soley on the output

Print all error messages to stderr (standard error) and not stdout (standard output):
This allows you to seperate the error messages from the normal program dialog using command line redirection.
You can print to the stderr using fprintf()

Code:

fprintf(stderr, "Seg Fault Test Location #%d\n", X);

To redirect stdout you can use the > character.

Code:

./hello > world.txt

now the output of hello will be written to world.txt
The same can be done for stderr using the >& characters.

How does this help you?
Well if you program has a lot of user prompting and dialog then it can be harder to notice your error messages. So in conjunction with an input file redirecting stdin and stdout allows you to just view the errors.

Use a macro to save yourself some typeing:
One macro I use a lot when trying to locate a seg fault is the following:

Code:

#define SEG(X) fprintf(stderr, "Seg Fault Test Location #%d\n", X)

Then I'll liberally apply them throughout my code (I generally only do one function at a time so I don't have so much cleanup)

Sorry if my comment on gdb was off topic. Sometimes it is more helpful to use though, like in my class on ADTs this semester. Every program was 500-600 lines about linked lists, stacks, queues, trees, and what not. Lots of pointers. Some segfaults were hard to find. And I didn't start using gdb until the last assignment.

If you don't have access to gdb or any of the tools listed in here, a macro I used (and still use for other purposes) is

Code:

#define DEBUG if(1)
// used like
DEBUG puts("This location");
// or can be used with blocks
DEBUG {
puts("You can put multiple statements here.");
puts("see!");
}

Then you can turn the statements off by changing the 1 to a 0 in the #define, that way you don't have to delete them until you are sure you are done with them.