Using a debugger Segmentation fault? GDB to the rescue!
But first... Let's talk about the quiz Let's talk about the previous homework assignment Let's talk about the current homework assignment
K findkey(v value) We want to use recursion for this We can't tell which subtree the value can be found in We need a way for a function to possibly return a value to us Many ways you can do this, but I suggest the following...
K findkey(v value) { K answer; findkeyhelper(root, value, answer); return answer; } void findkeyhelper(node<k,v> *node, V value, K& answer) { if (!node) { return; } if......... answer = // something, in some cases
Using a debugger What is a debugger? What debuggers exist? What debugger will we be using? How do we start up our debugger? How does our debugger get triggered? What can we do when we're in our debugger?
What is a debugger? A debugger is a programming tool that lets us inspect the state of our program Some development environments have debuggers integrated with them (Visual Studio, CLion, Xcode, Eclipse, etc.) Debuggers allow us to pause program execution, examine the contents of memory and variables as the program is running, and see what code is currently running Some debuggers will allow you to modify memory to test things out
What debuggers exist? On Windows, the most commonly used debugger is probably the one that comes with Visual Studio On Windows, Mac, Linux, and countless others, you can use gdb as a command-line debugger On Mac (and partially on Linux), you can use lldb similarly to gdb
What debugger will we be using? We will be talking about gdb It runs almost everywhere It's free Most tasks you'd try to perform with gdb are supported by other debuggers Using CodeBlocks, Cloud9, Linux, or ada, gdb will run directly (or with a nicer interface) If you're a Mac user, Xcode doesn't come with gdb, and you will need to use lldb instead
How do we start up our debugger? To use gdb to run a program, we type gdb and then the program we want to debug For the most useful results, we need to compile with -g We will then be taken from the bash command prompt to the gdb prompt All of our use of gdb will start with this prompt We need to tell gdb to Run our program with the 'r' command We can tell gdb to Quit with the 'q' command (or with ^D)
How does our debugger get triggered? Our debugger gets triggered when some exceptional circumstance triggers it These include: Segmentation fault (null or invalid pointer dereference) Infinite recursion (technically a segmentation fault) Control+C ( ^C ) abort() assert() [actually calls abort() under the hood] Integer division by zero
What can we do when we're in our debugger? backtrace (or bt) print a list of the functions currently running and which line of code is currently running in each frame n switch the current frame to the selected one info locals print out all local variables print expression prints out the result of executing the specified code
"Wait, my problem disappears when debugging it!" You probably have a non-initialized variable
Breakpoints A breakpoint is a specific instruction where we want the program to pause for us to take a look around We can create a breakpoint using the break command break filename:linenumber This will create a breakpoint at the specified line of code in the given file If wanted, the filename (and the colon) can be omitted in the case where there's a single file
Breakpoints To list your current breakpoints, you can type info break When you hit a breakpoint, you can type continue to continue execution To delete a breakpoint, you can type delete break number to delete the specified breakpoint To make an expression displayed every time your program stops, type display expression To see what expressions you have displaying, type info display To remove an expression, type undisplay number
Breakpoints When we are stuck with our program stopped (but not broken due to an error) we have several commands to use: continue Resume our program running, going until the next breakpoint or error next instruction Tell our program to move forward until the next line of code in our current stack frame (i.e., our current function) step to the next line Run the program until it reaches the next line of code
Helping the compiler help you Your compiler (g++ or clang++) can help you avoid some of these problems: -Wall Warn about all major easily detectable issues in your code -Wpedantic Warn about absolutely everything that could be an issue Some compilers are more helpful: With clang++: -fsanitize=address At runtime, create an error when using invalid memory -fsanitize=undefined At runtime, create an error when your code relies on behavior that C++ says is undefined