Return to main page
GDB Tutorial: Finding Segmentation Faults
This tutorial will show you how to use gdb's up function to find the cause of segmentation faults. I'll be using a
c++ program I wrote as an example. The complete source code can be found here:
mymovies.cpp
movie.h
movie.cpp
Here's the contents of mymovie.cpp, a program I wrote that uses "movie" objects. Each movie has a year (when it was
released) and a name (the title of the movie). In main, I create four movie pointers and store them in a list called
Pixar. Then I set the pointers to each point to their own movie objects. Finally, I use a for loop to iterate
through Pixar and print out the names of all the movies.
1 #include <iostream>
2 #include "movie.h"
3 using namespace std;
4
5 int main() {
6 Movie* TheIncredibles = new Movie("The Incredibles", 2004);
7 Movie* Up = new Movie("Up", 2009);
8 Movie* Brave = new Movie("Brave", 2012);
9 Movie* MonstersInc;
10 Movie* Pixar[4] = {TheIncredibles, MonstersInc, Up, Brave};
11
12 //print out the names of all the Pixar movies
13 for (int i = 0; i < 4; i++){
14 cout << Pixar[i]->getName() << endl;
15 }
16
17 return 0;
18 }
Let's compile the program. Remember that you should compile your program with -g if you want to use it with gdb.
$ g++ -g -c mymovies.cpp movie.cpp
$ g++ -g -o mymovies mymovies.o movie.o
So far, so good! Let's see what happens when I run it.
$ ./mymovies
The Incredibles
Segmentation fault (core dumped)
I'm getting a seg fault! I'm going to use gdb to figure out what happened.
$ gdb mymovies
I'm going to start off by just running my program in gdb and seeing what it tells me.
(gdb) run
Starting program: movieexample/mymovies
The Incredibles
Program received signal SIGSEGV, Segmentation fault.
0x4b801c86 in std::basic_string<char, std::char_traits<char>, std::allocator<char>
>::basic_string(std::string const) ()
from /usr/lib/libstdc++.so.6
Missing separate debuginfos, use: debuginfo-install libgcc-4.6.3-2.fc16.i686 libstdc++-4.6.3-2.fc16.i686
I already knew that it seg faulted, but now gdb is telling me that the segmentation fault occurred at address
0x4b801c86 in std::basic_string<char, std::char_traits<char>, std::allocator<char>
>::basic_string(std::string const) (), which is in /usr/lib/libstdc++.so.6. This isn't in my program, so it
doesn't seem very helpful! However, gdb has an "up" command that lets you go up a level in your program to the line
where you called that function.
I can safely assume that the basic_string function in std isn't the cause of our error. It's more likely that I
passed it something that it's not meant to deal with. Let's look at what called this function:
(gdb) up
#1 0x08048cb9 in Movie::getName (this=0x804870d) at movie.cpp:18
18 return name;
Okay, now we've got something we can work with! The getName() function must be calling the basic_string function
with a strange argument, or arguments. Let's look at the getName() function:
Here's the function call from Movie.h
string getName();
And here's the function definition from Movie.cpp
string Movie::getName(){
return name;
}
getName() should return name, a private member variable of Movie. That all looks fine! Let's look at what I'm passing to
getName(). Gdb tells us that I'm passing it this=0x804870d. We can find more information about "this" by using gdb's print
function.
(gdb) print this
$1 = (Movie * const) 0x804870d
Now we know we're passing it a movie pointer. Let's dereference the pointer to find out what it's pointing to.
(gdb) print *this
$2 = {year = 1527301251, name = }
No wonder getName() is having problems - there isn't a name for it to return! The value for year also doesn't make
sense. It looks like a garbage value, the leftover values that variables store before you initialize them. Let's figure out where
I'm passing this pointer to getName().
(gdb) up
#2 0x08048a97 in main () at mymovies.cpp:14
14 cout << Pixar[i]->getName() << endl;
We've found the line where the segmentation fault occurs! Looking back at main(), we see that this line gets run more than once:
12 //print out the names of all the Pixar movies
13 for (int i = 0; i < 4; i++){
14 cout << Pixar[i]->getName() << endl;
15 }
I run getName() on all the movies in Pixar. Did I forget to initialize a member of Pixar?
Looking back at main(), we can see that on line 9, a new pointer is created but it's not initialized.
9 Movie* MonstersInc;
We've found our problem! I need to go back and initialize MonstersInc.