Вы находитесь на странице: 1из 9

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-07-
2004, 03:00 #2
PM
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,
#3
03:06 PM
Gregor Rot Re: pointers : segmentation fault under Linux
Ernst Murnleitner wrote:
Posts: n/a
>>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-07-
2004, #4
03:22 PM
Gregor Re: pointers : segmentation fault under Linux
Rot Gregor Rot wrote:
> Ernst Murnleitner wrote:
Posts: n/a >
>>> 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-07-
2004, #5
04:11 PM
Martijn Re: pointers : segmentation fault under Linux
Lievaart 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

Вам также может понравиться