Debugging Segmentation Faults and Pointer Problems For new programmers, debugging errors associated with pointers can be a nightmare. "Segmentation Fault (core dumped)" is a pretty vague error message, and it's even worse when strange bugs start appearing that don't cause segmentation faults -- but that result in things like memory getting overwritten in unexpected ways. But finding problems with pointers is easier than you'd think. Those segfaults often turn out to be among the easiest bugs to find, and using special tools such as Valgrind, even finding buffer overflows is simplified.
What is a segmentation fault? When your program runs, it has access to certain portions of memory. First, you have local variables in each of your functions; these are stored in the stack. Second, you may have some memory, allocated during runtime (using either malloc, in C, or new, in C++), stored on the heap (you may also hear it called the "free store"). Your program is only allowed to touch memory that belongs to it -the memory previously mentioned. Any access outside that area will cause a segmentation fault. Segmentation faults are commonly refered to as segfaults. There are four common mistakes that lead to segmentation faults: dereferencing NULL, dereferencing an uninitialized pointer, dereferencing a pointer that has been freed (or deleted, in C++) or that has gone out of scope (in the case of arrays declared in functions), and writing off the end of an array. A fifth way of causing a segfault is a recursive function that uses all of the stack space. On some systems, this will cause a "stack overflow" report, and on others, it will merely appear as another type of segmentation fault. A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. 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 is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.
On Unix-like operating systems, a process that accesses an invalid memory address receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.
[edit] Example Here is an example of ANSI C code that should create a segmentation fault on platforms with memory protection: int main(){ char *s = "hello world"; *s = 'H'; }
When the program containing this code is compiled, the string "hello world" is placed in the section of the program binary marked as read-only; when loaded, the operating system places it with other strings and constant data in a read-only segment of memory. When executed, a variable, s, is set to point to the string's location, and an attempt is made to write an H character through the variable into the memory, causing a segmentation fault. Compiling such a program with a compiler that does not check for the assignment of read-only locations at compile time, and running it on a Unix-like operating system, produces the following runtime error: $ gcc segfault.c -g -o segfault $ ./segfault Segmentation fault
Backtrace from gdb: Program received signal SIGSEGV, Segmentation fault. 0x1c0005c2 in main () at segfault.c:6 6 *s = 'H';
The conditions under which segmentation violations occur and how they manifest themselves are specific to an operating system. Because a very common program error is a null pointer dereference (a read or write through the null pointer, a null pointer, used in C to mean "pointer to no object" and as an error indicator), most operating systems map the null pointer's address such that accessing it causes a segmentation fault. int* ptr = NULL; *ptr = 1;
This sample code creates a null pointer, and tries to assign a value to its non-existent target. Doing so causes a segmentation fault at runtime on many operating systems.
Another way to cause a segmentation fault is to recurse without a base case, which causes a stack overflow: int main(){ main(); }
A few causes of segmentation fault can be summarized as follows, (1) attempt to execute a program that does not compile correctly. Note that most compilers will not output a binary given a compile-time error. (2) buffer overruns (3) using uninitialized pointers (4) dereference NULL pointers (5) attempt to address memory the program does not own. (6) failure to check for data validity before using it. (7) failure to check for file open success before attempting to use the file pointer. Generally, segmentation faults occur because: a pointer of yours is either NULL, or points to random memory (probably never initialized to anything), or points to memory that was deleted. e.g. char* p1 = NULL; // initialized to null, which is good but not dereferencable on many systems char* p2; // not initialized at all char* p3 = new char[20]; // great, it's allocated delete [] p3; // but now it isn't anymore
Now, referencing any of these variables could cause a segmentation fault.
Segmentation Fault in example C program Code: printf("\nInput an integer value for x: "); scanf("%d", &x); printf("\nInput an integer value for y: "); scanf("%d", y);
Your missing the "&" from variable y in the 2nd scanf. always compile your code with "-Wall" , which shows these type of errors during compile time and & "-g" which includes debugging information in the binary for use in ddd / gdb. Code: gcc source.c -Wall -g -o executablefile
DISCUSSIONS Hi, i have this simple data structure : struct nodeProject { char key[100]; char name[1000]; struct linkProject *plink; }; struct linkProject { struct nodeProject *node; struct linkProject *next; }; Trough the program i make a structure, but then if i want to access let's say: nodeProject->linkProject->nodeProject->name (nodeProject and linkProject are used just to make clear what data types i have, otherwise that are pointers) i get an error under LINUX (GCC), but under WIndows everything works fine. If the "depth" doesn't involve linkProject, everything works fine (ex. nodeProject->name). Any idea? I think i got that data structure wrong somehow. Tnx, Greg
Gregor Rot
Gregor Rot 01-072004, 03:00 PM
#2
Ernst Re: pointers : segmentation fault under Linux Murnleitner > struct nodeProject { > char key[100]; Posts: n/a > char name[1000]; > struct linkProject *plink; > }; > > struct linkProject { > struct nodeProject *node; > struct linkProject *next; > }; > > > Trough the program i make a structure, but then if i want to access > let's say: > > nodeProject->linkProject->nodeProject->name -----------------------------| If it doesn`t work left of --| , I guess you haven't initialized linkProject pointer. So it writes somewhere into the memory, and a segmentation fault can be thrown or not, depending on the value which the pointer has. I always use a constructor in oder to set the pointers to 0 and test for validy: if (nodeProject && nodeProject->linkProject && ... ) nodeProject->linkProject->nodeProject->name ... Greetings Ernst
Ernst Murnleitner
Ernst Murnleitner 01-07-2004, 03:06 PM
#3
Gregor Rot Posts: n/a
Re: pointers : segmentation fault under Linux Ernst Murnleitner wrote: >>struct nodeProject { >>char key[100]; >>char name[1000]; >>struct linkProject *plink; >>}; >> >>struct linkProject { >>struct nodeProject *node; >>struct linkProject *next; >>}; >> >> >>Trough the program i make a structure, but then if i want to access >>let's say: >> >>nodeProject->linkProject->nodeProject->name > > -----------------------------| > If it doesn`t work left of --| , I guess you haven't initialized linkProject > pointer. > So it writes somewhere into the memory, and a segmentation fault can be > thrown or not, depending on the value which the pointer has. > I always use a constructor in oder to set the pointers to 0 and test for > validy: > > if (nodeProject && nodeProject->linkProject && ... ) > nodeProject->linkProject->nodeProject->name ... > > Greetings > Ernst > > I am afraid i have, under Windows (Dev-C++) everything works fine and the values are printed out correctly (name values). any other idea?
br, Greg
Gregor Rot
Gregor Rot 01-072004, 03:22 PM Gregor Rot Posts: n/a
#4 Re: pointers : segmentation fault under Linux Gregor Rot wrote: > Ernst Murnleitner wrote: > >>> struct nodeProject { >>> char key[100]; >>> char name[1000]; >>> struct linkProject *plink; >>> }; >>> >>> struct linkProject { >>> struct nodeProject *node; >>> struct linkProject *next; >>> }; >>> >>> >>> Trough the program i make a structure, but then if i want to access >>> let's say: >>> >>> nodeProject->linkProject->nodeProject->name >> >> >> -----------------------------| >> If it doesn`t work left of --| , I guess you haven't initialized >> linkProject >> pointer. >> So it writes somewhere into the memory, and a segmentation fault can be >> thrown or not, depending on the value which the pointer has. >> I always use a constructor in oder to set the pointers to 0 and test for >> validy:
>> >> if (nodeProject && nodeProject->linkProject && ... ) >> nodeProject->linkProject->nodeProject->name ... >> >> Greetings >> Ernst >> >> > I am afraid i have, under Windows (Dev-C++) everything works fine > and the values are printed out correctly (name values). > > any other idea? > > br, > Greg > Jupy, it works! Your advice helped. I checked every pointer connection and found out, that because i was reading data frm a file and checking #10 for end of line, under Linux the pointer structure didn't fill up (Linux doesn't use #10#13 and EOLN only #13 i suppose?) tnx, br, Greg
Gregor Rot
Gregor Rot 01-072004, 04:11 PM
#5
Martijn Lievaart
Re: pointers : segmentation fault under Linux On Wed, 07 Jan 2004 17:22:25 +0100, Gregor Rot wrote:
Posts: n/a
> Jupy, it works! Your advice helped. I checked every pointer connection > and found out, that because i was reading data frm a file and checking > #10 for end of line, under Linux the pointer structure didn't fill up > (Linux doesn't use #10#13 and EOLN only #13 i suppose?)
That is the kind of stuf that using text files shields you from You seem to have a text file that you open in binary mode. Sometimes text and binary are mixed in one file, but in that case you have to take care to define the text format. As you found out, text formats differ from OS to OS in the way they indicate EOL (f.i. Unix uses '\n', dos/windows uses "\n\r", classic mac used '\r'). Opening a file in text mode translates this on the fly to '\n'. If you do have a mixed text/binary file, define the text format yourself. Either use '\n' because it is easier in C/C++, or use "\r\n" because most of the internet protocols use it. If you don't have a mixed file, use text mode and all will be easy and well. BTW, you might do some more error checking, this should have been cought by the routine reading the file. HTH, M4 Martijn Lievaart
#6 Chris Dams
Re: pointers : segmentation fault under Linux Hi! Gregor Rot <> writes: >any other idea? Run the program in the debugger? Good luck, Chris Dams