![]() |
| | #1 |
| C Programmer Join Date: Apr 2004
Posts: 477
| 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:
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;
}
Next are some examples that cause segmentation faults or memory violations. Example 1.2 Code: int main() {
char *abc;
abc[0] = 'z';
return 0;
}
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;
}
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;
}
C++ arrays have the following properties:
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;
}
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;
}
Code: #include <iostream>
using namespace std;
int main() {
int* p = new int[100];
cout << p[100];
delete []p;
return 0;
}
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;
}
Code: #include <iostream>
using namespace std;
int main() {
int* p = new int[100];
cout << p[99];
delete []p;
return 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.
__________________ 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. |
| Stack Overflow is offline | |
| | #2 | |
| not-a-geek Join Date: Apr 2004
Posts: 208
| Quote:
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 :/
__________________ main() { int O[!0<<~-!0]; (!0<<!0)[O]+= ~0 +~(!0|!0<<!0); printf("a function calling "); } | |
| Nyda is offline | |
| | #3 |
| C Programmer Join Date: Apr 2004
Posts: 477
| Hi, I don't mind at all. All constructive feedback is welcomed. 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. |
| Stack Overflow is offline | |
| | #4 |
| I like code Join Date: Apr 2004
Posts: 131
| 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 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. EDIT: here is an example on using gdb based on some of SO's source. Code: [ryan]$ cat segfault.c
#include <stdio.h>
int main(void)
{
int num;
printf("Enter a number: ");
scanf("%d", num);
return 0;
}
[ryan]$ gcc -o segfault segfault.c -g
[ryan]$ ./segfault
f
[ryan]$ ./segfault
4
Segmentation fault
[ryan]$ gdb ./segfault
GNU gdb 6.1-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
[ryan]$ gcc -o segfault segfault.c -g
[ryan]$ ./segfault
Enter a number: 5
Segmentation fault
[ryan]$ gdb ./segfault
GNU gdb 6.1-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) run
Starting program: /home/ryan/Code/C/segfault
Enter a number: 5
Program received signal SIGSEGV, Segmentation fault.
0xb7ef672b in _IO_vfscanf () from /lib/tls/libc.so.6
(gdb) bt
#0 0xb7ef672b in _IO_vfscanf () from /lib/tls/libc.so.6
#1 0xb7f00c68 in scanf () from /lib/tls/libc.so.6
#2 0xb7fd0d20 in _IO_file_jumps () from /lib/tls/libc.so.6
#3 0x08048525 in _IO_stdin_used ()
#4 0xbffffa74 in ?? ()
#5 0x00000000 in ?? ()
#6 0xb7fd7fcc in ?? () from /lib/tls/libc.so.6
#7 0x080483f3 in main () at segfault.c:7
(gdb) quit
The program is running. Exit anyway? (y or n) y
[ryan]$
Hope this helps some. Last edited by Rouss; 12-13-2004 at 09:45 PM. |
| Rouss is offline | |
| | #5 |
| +++ OK NO CARRIER Join Date: Oct 2001
Posts: 10,262
| 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. Quzah.
__________________ Hundreds of thousands of dipshits can't be wrong. Are you up for the suck? |
| quzah is offline | |
| | #6 |
| Registered User Join Date: May 2004
Posts: 1,362
| But of course debugger's are also useful when you're not getting the right output, not necessarily a seg fault. But I guess thats kinda off topic.
__________________ |
| sand_man is offline | |
| | #7 |
| Banned Join Date: Aug 2001 Location: Visalia, CA, USA
Posts: 3,699
| 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 Last edited by master5001; 12-14-2004 at 07:51 AM. |
| master5001 is offline | |
| | #8 |
| C Programmer Join Date: Apr 2004
Posts: 477
| Hello, 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. |
| Stack Overflow is offline | |
| | #9 |
| & the hat of GPL slaying Join Date: Sep 2001
Posts: 5,730
| 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 Code: program-name < file-name Code: ./hello < world.txt 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); Code: ./hello > 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) Code: int main(void)
{
int x, y, z;
SEG(1);
x = 2;
SEG(2);
y = 3;
SEG(3);
z = 4;
SEG(4);
printf("%d %d %d\n", x, y, z);
SEG(5);
return 0;
}
For the macro to really be the most effective you need to do all three parts (make an input file, put all error messages to stderr, redirect stdin and stdout). |
| Thantos is offline | |
| | #10 |
| I like code Join Date: Apr 2004
Posts: 131
| 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!");
}
|
| Rouss is offline | |
| | #11 |
| Just Lurking Join Date: Oct 2002
Posts: 4,990
| The "print some information" comments remind me to mention assert.
__________________ 7. It is easier to write an incorrect program than understand a correct one. 40. There are two ways to write error-free programs; only the third one works.* |
| Dave_Sinkula is offline | |
| | #12 |
| and the hat of vanishing Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,214
| Beware - http://www.houghi.org/jargon/heisenbug.php Trying to examine the problem changes the problem. |
| Salem is offline | |
| | #13 |
| & the hat of GPL slaying Join Date: Sep 2001
Posts: 5,730
| Oh yes I've meant with that bug before. It was real fun trying to figure it out |
| Thantos is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Why am I getting segmentation fault on this? | arya6000 | C++ Programming | 6 | 10-12-2008 06:32 AM |
| segmentation fault... first time with unix... | theMethod | C Programming | 16 | 09-30-2008 02:01 AM |
| Segmentation fault | bennyandthejets | C++ Programming | 7 | 09-07-2005 05:04 PM |
| Segmentation fault | NoUse | C Programming | 4 | 03-26-2005 03:29 PM |
| Segmentation fault... | alvifarooq | C++ Programming | 14 | 09-26-2004 12:53 PM |