Pointer Assignment Segmentation Fault Linux

"Segfault" redirects here. For the website, see Segfault (website).

In computing, a segmentation fault (often shortened to segfault) or access violation is a fault, or failure condition, raised by hardware with memory protection, notifying an operating system (OS) the software has attempted to access a restricted area of memory (a memory access violation). On standard x86 computers, this is a form of general protection fault. The OS kernel will, in response, usually perform some corrective action, generally passing the fault on to the offending process by sending the process a signal. Processes can in some cases install a custom signal handler, allowing them to recover on their own,[1] but otherwise the OS default signal handler is used, generally causing abnormal termination of the process (a program crash), and sometimes a core dump.

Segmentation faults are a common class of error in programs written in languages like C that provide low-level memory access. They arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access. Another type of memory access error is a bus error, which also has various causes, but is today much rarer; these occur primarily due to incorrect physical memory addressing, or due to misaligned memory access – these are memory references that the hardware cannot address, rather than references that a process is not allowed to address.

Newer programming languages may employ mechanisms designed to avoid segmentation faults and improve memory safety. For example, the Rust programming language which appeared in 2010 employs an 'Ownership'[2] based model to ensure memory safety.[3]


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).

The term "segmentation" has various uses in computing; in the context of "segmentation fault", a term used since the 1950s, it refers to the address space of a program.[citation needed] With memory protection, only the program's own address space is readable, and of this, only the stack and the read-write portion of the data segment of a program are writable, while read-only data and the code segment are not writable. Thus attempting to read outside of the program's address space, or writing to a read-only segment of the address space, results in a segmentation fault, hence the name.

On systems using hardware memory segmentation to provide virtual memory, a segmentation fault occurs when the hardware detects an attempt to refer to a non-existent segment, or to refer to a location outside the bounds of a segment, or to refer to a location in a fashion not allowed by the permissions granted for that segment. On systems using only paging, an invalid page fault generally leads to a segmentation fault, and segmentation faults and page faults are both faults raised by the virtual memory management system. Segmentation faults can also occur independently of page faults: illegal access to a valid page is a segmentation fault, but not an invalid page fault, and segmentation faults can occur in the middle of a page (hence no page fault), for example in a buffer overflow that stays within a page but illegally overwrites memory.

At the hardware level, the fault is initially raised by the memory management unit (MMU) on illegal access (if the referenced memory exists), as part of its memory protection feature, or an invalid page fault (if the referenced memory does not exist). If the problem is not an invalid logical address but instead an invalid physical address, a bus error is raised instead, though these are not always distinguished.

At the operating system level, this fault is caught and a signal is passed on to the offending process, activating the process's handler for that signal. Different operating systems have different signal names to indicate that a segmentation fault has occurred. On Unix-like operating systems, a signal called SIGSEGV (abbreviated from segmentation violation) is sent to the offending process. On Microsoft Windows, the offending process receives a STATUS_ACCESS_VIOLATION exception.


The conditions under which segmentation violations occur and how they manifest themselves are specific to hardware and the operating system: different hardware raises different faults for given conditions, and different operating systems convert these to different signals that are passed on to processes. The proximate cause is a memory access violation, while the underlying cause is generally a software bug of some sort. Determining the root cause – debugging the bug – can be simple in some cases, where the program will consistently cause a segmentation fault (e.g., dereferencing a null pointer), while in other cases the bug can be difficult to reproduce and depend on memory allocation on each run (e.g., dereferencing a dangling pointer).

The following are some typical causes of a segmentation fault:

  • Attempting to access a nonexistent memory address (outside process's address space)
  • Attempting to access memory the program does not have rights to (such as kernel structures in process context)
  • Attempting to write read-only memory (such as code segment)

These in turn are often caused by programming errors that result in invalid memory access:

  • Dereferencing a null pointer, which usually points to an address that's not part of the process's address space
  • Dereferencing or assigning to an uninitialized pointer (wild pointer, which points to a random memory address)
  • Dereferencing or assigning to a freed pointer (dangling pointer, which points to memory that has been freed/deallocated/deleted)
  • A buffer overflow
  • A stack overflow
  • Attempting to execute a program that does not compile correctly. (Some compilers will output an executable file despite the presence of compile-time errors.)

In C code, segmentation faults most often occur because of errors in pointer use, particularly in C dynamic memory allocation. Dereferencing a null pointer will always result in a segmentation fault, but wild pointers and dangling pointers point to memory that may or may not exist, and may or may not be readable or writable, and thus can result in transient bugs. For example:

char*p1=NULL;// Null pointerchar*p2;// Wild pointer: not initialized at all.char*p3=malloc(10*sizeof(char));// Initialized pointer to allocated memory// (assuming malloc did not fail)free(p3);// p3 is now a dangling pointer, as memory has been freed

Now, dereferencing any of these variables could cause a segmentation fault: dereferencing the null pointer generally will cause a segfault, while reading from the wild pointer may instead result in random data but no segfault, and reading from the dangling pointer may result in valid data for a while, and then random data as it is overwritten.


The default action for a segmentation fault or bus error is abnormal termination of the process that triggered it. A core file may be generated to aid debugging, and other platform-dependent actions may also be performed. For example, Linux systems using the grsecurity patch may log SIGSEGV signals in order to monitor for possible intrusion attempts using buffer overflows.


Writing to read-only memory[edit]

Writing to read-only memory raises a segmentation fault. At the level of code errors, this occurs when the program writes to part of its own code segment or the read-only portion of the data segment, as these are loaded by the OS into read-only memory.

Here is an example of ANSI C code that will generally cause a segmentation fault on platforms with memory protection. It attempts to modify a string literal, which is undefined behavior according to the ANSI C standard. Most compilers will not catch this at compile time, and instead compile this to executable code that will crash:

intmain(void){char*s="hello world";*s='H';}

When the program containing this code is compiled, the string "hello world" is placed in the rodata section of the program executable file: the read-only section of the data segment. 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 of the core file from GDB:


This code can be corrected by using an array instead of a character pointer, as this allocates memory on stack and initializes it to the value of the string literal:

chars[]="hello world";s[0]='H';// equivalently, *s = 'H';

Even though string literals should not be modified (this has undefined behavior in the C standard), in C they are of type[4][5][6], so there is no implicit conversion in the original code (which points a at that array), while in C++ they are of type, and thus there is an implicit conversion, so compilers will generally catch this particular error.

Null pointer dereference[edit]

Because a very common program error is a null pointerdereference (a read or write through 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.


This sample code creates a null pointer, and then tries to access its value (read the value). Doing so causes a segmentation fault at runtime on many operating systems.

Dereferencing a null pointer and then assigning to it (writing a value to a non-existent target) also usually causes a segmentation fault:


The following code includes a null pointer dereference, but when compiled will often not result in a segmentation fault, as the value is unused and thus the dereference will often be optimized away by dead code elimination:

Buffer overflow[edit]

Main article: Buffer overflow

Stack overflow[edit]

Main article: Stack overflow

Another example is recursion without a base case:


which causes the stack to overflow which results in a segmentation fault.[7] Infinite recursion may not necessarily result in a stack overflow depending on the language, optimizations performed by the compiler and the exact structure of a code. In this case, the behavior of unreachable code (the return statement) is undefined, so the compiler can eliminate it and use a tail call optimization that might result in no stack usage. Other optimizations could include translating the recursion into iteration, which given the structure of the example function would result in the program running forever, while probably not overflowing its stack.

See also[edit]


External links[edit]

Example of human generated signal
Segmentation fault on an EMV keypad

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.

This tutorial assumes that you have a basic knowledge of pointers such as can be acquired by reading a pointer tutorial. It would help to be running a system that has a debugger such as GDB, or to at least have sufficient familiarity with GDB-like debuggers to understand the examples presented. Finally, for finding buffer overflows and other invalid uses of memory, you will fare best with Valgrind, though none of the examples will use it.

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 referred 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.

The strategy for debugging all of these problems is the same: load the core file into GDB, do a backtrace, move into the scope of your code, and list the lines of code that caused the segmentation fault.

For instance, running on a Linux system, here's an example session: % gdb example core This just loads the program called example using the core file called "core". The core file contains all the information needed by GDB to reconstruct the state of execution when the invalid operation caused a segmentation fault.

Once we've loaded up gdb, we get the following: Some copyright info Core was generated by `example'. Program terminated with signal 11, Segmentation fault. Some information about loading symbols #0 0x0804838c in foo() () at t.cpp:4 4 *x = 3; So, execution stopped inside the function called foo() on line 4, which happened to be the assignment of the number 3 to the location pointed to by x. This is a goldmine of information: we already know exactly where the problem happened and which pointer was involved.

(gdb) list 1 void foo() 2 { 3 char *x = 0; 4 *x = 3; 5 } 6 7 int main() 8 { 9 foo(); 10 return 0; (gdb) Since this is a somewhat contrived example, we can immediately find the error. The pointer x is initialized to 0, equivalent to NULL (in fact, NULL is a stand-in for 0), and we know that it's a no-no to then try to access that pointer.

But what if it weren't so obvious? Simply printing the value of the pointer can often lead to the solution. In this case: (gdb) print x $1 = 0x0 Printing out x reveals that it points to memory address 0x0 (the 0x indicates that the value following it is in hexadecimal, traditional for printing memory addresses). The address 0x0 is invalid -- in fact, it's NULL. If you dereference a pointer that stores the location 0x0 then you'll definitely get a segmentation fault, just as we did.

If we'd gotten something more complicated, such as execution crashing inside a system call or library function (perhaps because we passed an uninitialized pointer to fgets), we'd need to figure out where we called the library function and what might have happened to cause a segfault within it. Here's an example from another debugging session: #0 0x40194f93 in strcat () from /lib/tls/libc.so.6 (gdb) This time, the segfault occurred because of something inside strcat. Does this mean the library function did something wrong? Nope! It means that we probably passed a bad value to the function. To debug this, we need to see what we passed into strcat.

So let's see what function call we made that led to the segfault. (gdb) backtrace #0 0x40194f93 in strcat () from /lib/tls/libc.so.6 #1 0x080483c9 in foo() () at t.cpp:6 #2 0x080483e3 in main () at t.cpp:11 (gdb) Backtrace lists the function calls that had been made at the time the program crashed. Each function is directly above the function that called it. So foo was called by main in this case. The numbers on the side (#0, #1, #2) also indicate the order of calls, from most recent to longest ago.

To move from viewing the state within each function (encapsulated in the idea of a stack frame), we can use the up and down commands. Right now, we know we're in the strcat stack frame, which contains all of the local variables of strcat, because it's the top function on the stack. We want to move "up" (toward the higher numbers); this is the opposite of how the stack is printed. (gdb) up #1 0x080483c9 in foo() () at t.cpp:6 6 strcat(x, "end"); (gdb) This helps a little -- we know that we have a variable called x and a constant string. We should probably lookup the strcat function at this point to make sure that we got the order of arguments correct. Since we did, the problem must be with x. (gdb) print x $1 = 0x0 There it is again: a NULL pointer. The strcat function must be derefencing a NULL pointer that we gave it, and even though it's a library function, it doesn't do anything magical.

NULL pointers are generally pretty easy to work with -- once we've found one, we know that somewhere along the line, we didn't allocate some memory that we should have. It's just a question of where. A common mistake is to not check the return from malloc to make sure that the system isn't out of memory. Another common mistake is to assume that a function that calls malloc doesn't return NULL even though it returns the result of malloc. Note that in C++, when you call new, it will throw an exception, bad_alloc, if sufficient memory cannot be allocated. Your code should be prepared to handle this situation cleanly, and if you choose to catch the exception and return NULL inside a function that ordinarily returns a new'ed pointer, this advice still holds. char *create_memory() { char *x = malloc(10); if(x == NULL) { return NULL; } strcpy(x, "a string"); return x; } void use_memory() { char *new_memory = create_memory(); new_memory[0] = 'A'; /* make it a capital letter */ } We did a good thing by checking to make sure that malloc succeeds before using the memory in create_memory, but we don't check to make sure that create_memory returns a valid pointer! Shame on us. This is a bug that won't catch you until you're running your code on a real system unless you explicitly test your code in low memory situations.

Dereferencing an Uninitialized Pointer

Figuring out whether or not a pointer has been initialized is a bit harder than figuring out whether a pointer is NULL. The best way to avoid using an uninitialized pointer is to set your pointers to NULL when you declare them (or immediately initialize them). That way, if you do use a pointer that hasn't had memory allocated for it, you will immediately be able to tell.

If you don't set your pointers to NULL when you declare them, then you'll have a much harder time of it (remember that non-static variables aren't automatically initialized to anything in C or C++). You might need to figure out if 0x4025e800 is valid memory. One way you can get a sense of this in GDB is by printing out the addresses stored in other pointers you've allocated. If they're fairly close together, you've probably correctly allocated memory. Of course, there's no guarantee that this rule of thumb will hold on all systems.

In some cases, your debugger can tell you that an address is invalid based on the value stored in the pointer. For instance, in the following example, GDB indicates that the char* x, which I set to point to the memory address "30", is not accessible. (gdb) print x $1 = 0x1e <out of bounds> (gdb) print *x Cannot access memory at address 0x1e Generally, though, the best way to handle such a situation is just to avoid having to rely on memory's being close together or obviously invalid. Set your variables to NULL from the beginning.

Dereferencing Freed Memory

This is another tricky bug to find because you're working with memory addresses that look valid. The best way to handle such a situation is again preventative: set your pointer to point to NULL as soon as you've freed it. That way, if you do try to use it later, then you'll have another "dereferencing NULL" bug, which should be much easier to track.

Another form of this bug is the problem of dealing with memory that has gone out of scope. If you declare a local array such as char *return_buffer() { char x[10]; strncpy(x, "a string", sizeof(x)); return x; } then the array, x, will no longer be valid once the function returns. This is a really tricky bug to find because once again the memory address will look valid when you print it out in GDB. In fact, your code might even work sometimes (or just display weird behavior by printing whatever happens to be on the stack in the location that used to be the memory of the array x). Generally, the way you'll know if you have this kind of bug is that you'll get garbage when you print out the variable even though you know that it's initialized. Watch out for the pointers returned from functions. If that pointer is causing you trouble, check the function and look for whether the pointer is pointing to a local variable in the function. Note that it is perfectly fine to return a pointer to memory allocated in the function using new or malloc, but not to return a pointer to a statically declared array (e.g., char x[10]).

Tools such as Valgrind can be immensely helpful in tracking down these bugs because they watch memory to ensure that it's valid. If it isn't, Valgrind will alert you. Our Valgrind tutorial goes into more detail about finding this sort of bug.

Of course, the best solution is simply to avoid ever doing anything like this. Technically, you could use a static buffer, which would allow you to have a permanent buffer you could pass around. But this is only asking for trouble if you later decide, for whatever reason, that you don't need it to be static (if you forget why you made it static in the first place, for instance).

Writing off the end of the array

Generally, if you're writing off the bounds of an array, then the line that caused the segfault in the first place should be an array access. (There are a few times when this won't actually be the case -- notably, if the fact that you wrote off an array causes the stack to be smashed -- basically, overwriting the pointer that stores where to return after the function completes.)

Of course, sometimes, you won't actually cause a segfault writing off the end of the array. Instead, you might just notice that some of your variable values are changing periodically and unexpectedly. This is a tough bug to crack; one option is to set up your debugger to watch a variable for changes and run your program until the variable's value changes. Your debugger will break on that instruction, and you can poke around to figure out if that behavior is unexpected. (gdb) watch [variable name] Hardware watchpoint 1: [variable name] (gdb) continue ... Hardware watchpoint 1: [variable name] Old value = [value1] New value = [value2] This approach can get tricky when you're dealing with a lot of dynamically allocated memory and it's not entirely clear what you should watch. To simplify things, use simple test cases, keep working with the same inputs, and turn off randomized seeds if you're using random numbers!

Stack Overflows

A stack overflow isn't the same type of pointer-related problem as the others. In this case, you don't need to have a single explicit pointer in your program; you just need a recursive function without a base case. Nevertheless, this is a tutorial about segmentation faults, and on some systems, a stack overflow will be reported as a segmentation fault. (This makes sense because running out of memory on the stack will violate memory segmentation.)

To diagnose a stack overflow in GDB, typically you just need to do a backtrace: (gdb) backtrace #0 foo() () at t.cpp:5 #1 0x08048404 in foo() () at t.cpp:5 #2 0x08048404 in foo() () at t.cpp:5 #3 0x08048404 in foo() () at t.cpp:5 [...] #20 0x08048404 in foo() () at t.cpp:5 #21 0x08048404 in foo() () at t.cpp:5 #22 0x08048404 in foo() () at t.cpp:5 ---Type If you find a single function call piling up an awfully large number of times, this is a good indication of a stack overflow.

Typically, you need to analyze your recursive function to make sure that all the base cases (the cases in which the function should not call itself) are covered correctly. For instance, in computing the factorial function int factorial(int n) { // What about n < 0? if(n == 0) { return 1; } return factorial(n-1) * n; } In this case, the base case of n being zero is covered, but what about n < 0? On "valid" inputs, the function will work fine, but not on "invalid" inputs like -1.

You also have to make sure that your base case is reachable. Even if you have the correct base case, if you don't correctly progress toward the base case, your function will never terminate. int factorial(int n) { if(n <= 0) { return 1; } // Ooops, we forgot to subtract 1 from n return factorial(n) * n; }


While segmentation faults can be nasty and difficult to track down when you are first learning to program, over time you will start to see them as falling into a small number of patterns that are relatively easy to track down. This tutorial hasn't covered every possible scenario for causing segmentation faults, but it touches on many of the basic problems you may encounter.

Related articles

Read more about debugging strategies

Learn more about using GDB

Using Valgrind to hunt memory errors

Read more about the psychological aspects of programming

Learn more about secure coding and avoiding pointer problems


Leave a Reply

Your email address will not be published. Required fields are marked *