cse 332: c++ debugging why debug a program? when your program crashes –finding out where it...
TRANSCRIPT
CSE 332: C++ debugging
Why Debug a Program?
• When your program crashes– Finding out where it crashed– Examining program memory at that point
• When a bug occurs in your program– Watching program variables – Identifying where a problem occurs (and why)
• Tracing through a program’s behaviors– Learning what a program does– Good basic testing approach
CSE 332: C++ debugging
Debugging on Various Platforms• We’ll use Visual Studio’s graphical debugger
– Much more on this as we go through the semester– Set command line arguments in the project properties – It’s also good to know about common text-based tools
• gdb– Debugger provided with the g++ compiler (e.g., on Linux)– Using –g switch embeds debug info during compilation
• dbx– Debugger provided with Sun CC– Also requires –g switch to embed debug symbols
CSE 332: C++ debugging
Some Essential Debugging Commands• start (or restart) execution in the debugger
– Visual Studio: F5 (Start Debugging)– gdb: run (also give its command line arguments)
• execute one line, stepping into any functions– Visual Studio: F11 (Step Into)– gdb: step
• execute one line, stepping over any functions– VS: F10 (Step Over)– gdb: next
• set breakpoint at a line or function entry point– VS: F9 (Toggle Breakpoint)– gdb: break (can give file and line, function, etc.)
CSE 332: C++ debugging
“Core” Dumps
• A program dumps a memory image when it crashes– creates a file (called “core” on Linux) and then exits– this happens when a program receives certain signals:
• Segmentation fault– accessed memory it does not own
– or dereferenced a 0 pointer
• Bus error– divided by zero
– corrupted stack
• Debuggers are very useful to examine “core” files– When your program crashes within Visual Studio– On Linux: gdb myprogram core
CSE 332: C++ debugging
Debugging an Example Program• A debugger helps us observe a program’s behavior
– Step through (and into) functions– Watching the call stack and variable values
• But, before we start using the fancy tools…– What do we expect the program to do?– How might the program fail?– Can we make predictions and test them?
• Thinking: the most powerful way to debug– Scientific method should guide what you do
• hypothesis, prediction, experiment, analysis
– Tools can help you follow this disciplined approach faster
CSE 332: C++ debugging
What We Expect the Example Program To Do
• Called with command line arguments./prefix_adder + 8 + 9 10
• Calculates prefix addition expressions+ 8 + 9 10 + + 8 9 10
• These are equivalent to their infix versions(8 + (9 + 10)) ((8 + 9) + 10)
• Key idea: walk through expresion, calculate value
+
+8
9 10
1
2 3
4 5
+
+
8 9
10
1
2
3 4
5
same result
different order
CSE 332: C++ debugging
How the Example Program Can Fail
• Too few arguments in expression./prefix_adder + 8 + 9
• Cannot calculate result+ 8 + 9 (needs another value to finish 2nd + operation)
• Try this on your own in the studio, for practice
+
+8
9
1
2 3
4 ???
CSE 332: C++ debugging
Example Program Header File // prefix_adder.h//// author: Chris Gill [email protected]//// purpose: Declarations for a simple prefix adder program,
which// takes the command line arguments as a prefix
addition // expression and computes an integer result.
#ifndef PREFIX_ADDER_H#define PREFIX_ADDER_H
// Function prototypes.void usage (char * program_name);int parse_and_compute (int & current_index, int last_index, char *argv[]);
#endif /* PREFIX_ADDER_H */
CSE 332: C++ debugging
Example Program Source File / Usage Function// prefix_adder.cc//// author: Chris Gill [email protected]//// purpose: definitions for a simple prefix adder program, which// takes the command line arguments as a prefix addition // expression and computes an integer result.
#include "prefix_adder.h"
#include <iostream> // For std output stream and manipulators.#include <string> // For standard C++ strings.#include <sstream> // For standard string streams.#include <cstring> // For C-style string functions
// Helper function to print out the program's usage message.void usage (char * program_name) {
cout << "Usage: " << program_name << " <argument> [<argument>]..." << endl << "Purpose: computes program arguments as prefix addition expression" << endl;}
CSE 332: C++ debugging
Example Program Main Functionint main (int argc, char *argv[]){ // A few useful constants for argument positions const int minimum_arguments = 2; const int starting_index = 1; const int program_name_index = 0;
if (argc < minimum_arguments || strcmp (argv[starting_index], "--help") == 0) {
usage (argv[program_name_index]); return 1; }
try {
// Pass the current and last index to use, and the array, to the // expression parsing function, and store the result. int current_position = starting_index; int value = parse_and_compute (current_position, argc - 1, argv);
// Print out the result, and return success value. cout << "The value calculated is " << value << endl; return 0; } catch (...) {
cout << "caught exception" << endl; return -1; }}
CSE 332: C++ debugging
Example Program Parsing Function// Helper function to parse the input symbols and compute a value.int parse_and_compute (int & current_index, int last_index, char *argv[]) {
// make sure we're still in the argument range if (current_index > last_index) { throw 1; }
// look for a single-symbol addition operator if (strlen (argv[current_index]) == 1 && *(argv[current_index]) == '+') {
int first_operand = parse_and_compute (++current_index, last_index, argv); int second_operand = parse_and_compute (current_index, last_index, argv); return first_operand + second_operand; }
// treat anything else as an integer else {
int result; istringstream i (argv[current_index++]); i >> result; return result;
}}