CMPSC 311 – Introduction to Systems Programming
Professors and
(Slides are mostly by Professors Patrick McDaniel and )
CMPSC 311 – Introduction to Systems Programming
Copyright By PowCoder代写 加微信 powcoder
• Often the most complicated and time-consuming part of developing a program is debugging.
• Figuring out where your program diverges from your idea of what the code should be doing.
• Confirm that your program is doing what you expect to be doing. • Finding and fixing bugs …
CMPSC 311 – Introduction to Systems Programming
Think before you debug
• When something went wrong, I’d reflexively start to dig in to the problem, examining stack traces, sticking in print statements, invoking a debugger, and so on. But Ken would just stand and think, ignoring me and the code we’d just written. After a while I noticed a pattern: Ken would often understand the problem before I would, and would suddenly announce, “I know what’s wrong.” He was usually correct. I realized that Ken was building a mental model of the code and when something broke it was an error in the model. By thinking about *how* that problem could happen, he’d intuit where the model was wrong or where our code must not be satisfying the model.
CMPSC 311 – Introduction to Systems Programming
Rubber duck debugging
• The name is a reference to a story in the book The Pragmatic Programmer in which a programmer would carry around a rubber duck and debug their code by forcing themself to explain it, line-by-line, to the duck.
CMPSC 311 – Introduction to Systems Programming
Printing/Logging
• One way to debug is to print out the values of variables and memory at different points
• e.g., printf( “My variable value is %d”, myvar );
CMPSC 311 – Introduction to Systems Programming
• assert() is a function provided by C in which you place statements in code that must always be true, where the process aborts if it is not
• Check to make sure your assumptions about inputs/logic are always true
• Syntax: Examples:
assert( i>= 0 ); // Checks value
assert( ptr != NULL ); // Checks non-NULL pointer assert( (ptr = malloc(100)) != NULL ); // Confirms malloc successful assert( func(10, 20) ); // Confirms function returns 0
Note: These are sometimes called logic or program guards.
assert( expression );
CMPSC 311 – Introduction to Systems Programming
Demonstration function
#include
int factorial( int i ) {
assert( i>=0 ); if ( i <= 1 ) {
return( i ); }
return factorial(i-1)*i;
int main(int argc, char** argv) { int i = 5;
if (argc > 1) {
i = atoi(argv[1]);
printf(“Factorial of %d: %d\n”,i , factorial(i)); return( 0 );
CMPSC 311 – Introduction to Systems Programming
Demonstration function
#include
int factorial( int i ) {
assert( i>=0 );
if ( i <= 1 ) {
)-;g debugging.c -o debugging ./debugging
Factorial roeftu5r:n(12f0actorial(i-1)*i );
./debugging 4
Factorial of 4: 24
a-r1gv) { debugging:indtebiug=gi5n;g.c:7: factorial: Assertion `i >= 0′ failed. Aborted
if (argc > 1) {
i = atoi(argv[1]);
printf(“Factorial of %d: %d\n”,i , factorial(i)); return( 0 );
CMPSC 311 – Introduction to Systems Programming
The debugger
• A debugger is a program that runs your program within a controlled environment:
• Control aspects of the environment that your program will run in.
• Start your program or connect up to an already-started process.
• Make your program stop for inspection or under specified conditions.
• Step through your program one line at a time, or one machine instruction at a time. • Inspect the state of your program once it has stopped.
• Change the state of your program and then allow it to resume execution.
• In UNIX/Linux environments, the debugger used most often is gdb (the GNU Debugger) and is lldb up and coming (on OSX, Linux, …)
CMPSC 311 – Introduction to Systems Programming
• You run the debugger by passing the program to gdb $ gdb [program name]
• This is an interactive terminal-based debugger
• Invoking the debugger does not start the program, but simply drops you into
the gdb environment.
$ gdb debugging
GNU gdb (GDB) 7.5.91.20130417-cvs-ubuntu
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
There is NO WARRANTY, to the extent permitted by law. Type “show copying” and “show warranty” for details.
This GDB was configured as “x86_64-linux-gnu”.
For bug reporting instructions, please see:
Reading symbols from /home/mcdaniel/src/debugging/debugging…done.
CMPSC 311 – Introduction to Systems Programming
• You run the debugger by passing the program to gdb $ gdb [program name]
• This is an interactive terminal-based debugger
• Invoking the debugger does not start the program, but simply drops you into
the gdb environment.
$ gdb debugging
GNU gdb (GDB) 7.5.91.20130417-cvs-ubuntu
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
You can always get help for any command
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type “show copying” and “show warranty” for details.
For bug reporting instructions, please see:
Reading symbols from /home/mcdaniel/src/debugging/debugging…done. (gdb)
CMPSC 311 – Introduction to Systems Programming
gdb with a user interface
• You can also get a simple terminal interface by starting the debugger …
• This walks you through the code and makes debugging easier. The commands are the same.
• Tools like VS Code integrate the gdb function into the editor/IDE
CMPSC 311 – Introduction to Systems Programming
Running the program
• Once you enter the program, you must start the program running, using the run command
Starting program: /root/project/debugging Factorial of 5: 120
[Inferior 1 (process 149) exited normally] (gdb)
• If you have arguments to pass to the program, simply add them to the run command line
(gdb) run 12
Starting program: /root/project/debugging 12 Factorial of 12: 479001600
[Inferior 1 (process 153) exited normally] (gdb)
CMPSC 311 – Introduction to Systems Programming
Looking at code
• If want to look at regions of code, so use the list command
• shows 10 lines at a time, centered around the target • you can specify a line number (in the current file),
• or specify a function name
(gdb) list 4
1 #include
2 #include
3 #include
5 int factorial(int i) 6{
7 assert(i >= 0); // ** CHECK **
8 if (i <= 1) {
(gdb) l main 10
14 int 15{ 16
return (factorial(i - 1) * i);
main(int argc, char** argv)
int i; if(argc>1){
9 10} (gdb)
return (i); 18 19}
i = atoi(argv[1]);
• Most commands are aliased with single character (l)
CMPSC 311 – Introduction to Systems Programming
Breakpoints
• A breakpoint is a position in the code you wish for the debugger to stop and wait for your commands
break [function_name | line_number]
• Breakpoints are set using the break (b) command
• Each one is assigned a number you can reference later
• You can delete the breakpoint by using the delete (d) command delete [breakpoint_number]
(gdb) b factorial
Breakpoint 1 at 0x400587: file debugging.c, line 6. (gdb) b 16
Breakpoint 2 at 0x4005db: file debugging.c, line 16. (gdb) delete 1
CMPSC 311 – Introduction to Systems Programming
Conditional Breakpoints
• A conditional breakpoint is a point where you want the debugger only if the condition holds
• Breakpoints are set using the cond command
cond [breakpoint_number] (expr)
7 assert(i >= 0); // ** CHECK ** (gdb) b 7
Breakpoint 1 at 0x6e5: file debugging.c, line 7. (gdb) cond 1 i<=1
Starting program: /root/project/debugging
Breakpoint 1, factorial (i=1) at debugging.c:7 7 assert(i >= 0); // ** CHECK ** (gdb) c
Continuing.
Factorial of 5: 120
[Inferior 1 (process 157) exited normally]
CMPSC 311 – Introduction to Systems Programming
Conditional Breakpoints
• A conditional breakpoint is a point where you want the debugger only if the condition holds
• Alternately, breakpoints can be set with if expression
b [line | function] if (expr)
7 assert(i >= 0); // ** CHECK ** (gdb) b 7 if i<=1
Breakpoint 1 at 0x6e5: file debugging.c, line 7. (gdb) r
Starting program: /root/project/debugging
Breakpoint 1, factorial (i=1) at debugging.c:7 7 assert(i >= 0); // ** CHECK ** (gdb) c
Continuing.
Factorial of 5: 120
[Inferior 1 (process 165) exited normally]
CMPSC 311 – Introduction to Systems Programming
Seeing breakpoints
• If you want to see your breakpoints use the info breakpoints command
(gdb) info breakpoints Num Type
1 breakpoint
2 breakpoint
Address What
keep y 0x00000000000006e5 in factorial at debugging.c:7 keep y 0x000000000000075c in main at debugging.c:22
• The info command allows you see lots of information about the state of your environment and program
(gdb) help info
Generic command for showing things about the program being debugged.
List of info subcommands:
info address — Describe where symbol SYM is stored
info all-registers — List of all registers and their contents info args — Argument variables of current stack frame
CMPSC 311 – Introduction to Systems Programming
Saving breakpoints
• You can save breakpoints to a file for use later using save command
(gdb) b factorial
Breakpoint 1 at 0x6e5: file debugging.c, line 7. (gdb) b 22
Breakpoint 2 at 0x75c: file debugging.c, line 20. (gdb) save breakpoints bpoints.txt
Saved to file ‘bpoints.txt’.
• You can load the breakpoints from a file later using source command
gdb debugging
(gdb) source bpoints.txt
Breakpoint 1 at 0x6e5: file debugging.c, line 7. Breakpoint 2 at 0x75c: file debugging.c, line 20. (gdb)
CMPSC 311 – Introduction to Systems Programming
Watchpoints
• Watchpoints (also known as a data breakpoint) stop execution whenever the value of an variable changes, without a particular place where it happens.
• The simplest form is simply waiting for a variable to change
(gdb) b main
Breakpoint 1 at 0x737: file debugging.c, line 17. (gdb) run 4
Starting program: /root/project/debugging 4
Breakpoint 1, main (argc=2, argv=0x7fffffffe718) at debugging.c:17 warning: Source file is more recent than executable.
17 if (argc > 1) {
(gdb) watch i
Hardware watchpoint 2: i (gdb) c
Continuing.
Hardware watchpoint 2: i
Old value = 5
New value = 4
0x0000555555554753 in main (argc=2, argv=0x7fffffffe718) at debugging.c:18 18 i = atoi(argv[1]);
CMPSC 311 – Introduction to Systems Programming
Examining the stack
• You can always tell where you are in the program by using the where command, which gives you a stack and the specific line number you are one
(gdb) b 7 if i<=1
Breakpoint 1 at 0x6e5: file debugging.c, line 7. (gdb) run 4
Starting program: /root/project/debugging 4
Breakpoint 1, factorial (i=1) at debugging.c:7 7 assert(i >= 0); // ** CHECK ** (gdb) where
#0 factorial (i=1) at debugging.c:7
#1 0x0000555555554722 in factorial (i=2) at debugging.c:11
#2 0x0000555555554722 in factorial (i=3) at debugging.c:11
#3 0x0000555555554722 in factorial (i=4) at debugging.c:11
#4 0x0000555555554764 in main (argc=2, argv=0x7fffffffe718) at debugging.c:20 (gdb)
CMPSC 311 – Introduction to Systems Programming
Climbing and descending the stack
• You can move up and down the stack and see variables by using the up and down commands
#1 0x0000555555554722 in factorial (i=2) at 11 return (factorial(i – 1) * i); (gdb) p i
#2 0x0000555555554722 in factorial (i=3) at 11 return (factorial(i – 1) * i); (gdb) p i
(gdb) down
#1 0x0000555555554722 in factorial (i=2) at 11 return (factorial(i – 1) * i); (gdb) p i
(gdb) down
#0 factorial (i=1) at debugging.c:7
7 assert(i >= 0); // ** CHECK ** (gdb) p i
debugging.c:11
debugging.c:11
debugging.c:11
CMPSC 311 – Introduction to Systems Programming
Printing variables
• At any point in the debug session can print the value of any variable you want by printing its value using
print[/
• Dictate the output formatted with o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), and s(string)
(gdb) p values
$1 = “\001\002\003\004” (gdb) p/x values
$2 = {0x1, 0x2, 0x3, 0x4} (gdb) p val1
$3 = 4283787007
(gdb) p/x val1
$4 = 0xff5566ff
(gdb) p val2
$5 = 2.45677996
int myvalues() {
char values[] = { 0x1, 0x2, 0x3, 0x4 }; uint32_t val1 = 0xff5566ff;
float val2 = 2.45678;
return 0; // breakpoint here
CMPSC 311 – Introduction to Systems Programming
Examining memory
• You examine memory regions using the x command
x [/
• Modify the output using a number of values formatted with [oxdutfais] type and size are b(byte), h(halfword), w(word), g(giant, 8 bytes).
(gdb) x buf 0x555555756260: (gdb) x/8xb buf 0x555555756260: (gdb) x/xg buf 0x555555756260: (gdb) x buf 0x555555756260: (gdb) x &buf 0x7fffffffe5f8: (gdb)
0xefefefef
0xef 0xef 0xef 0xef 0xef 0xef 0xef 0xef 0xefefefefefefefef
0xefefefefefefefef
0x0000555555756260
int myexamine() {
char *buf = NULL;
buf = malloc( 8 );
memset( buf, 0xef, 8 ); return 0; // breakpoint here
CMPSC 311 – Introduction to Systems Programming
Walking the program
• There are four ways to advance the program in gdb • next (n) steps the program forward one statement
CMPSC 311 – Introduction to Systems Programming
Walking the program
• There are four ways to advance the program in gdb
• next (n) steps the program forward one statement
• step (s) moves the program forward one statement, but “steps into” a function
CMPSC 311 – Introduction to Systems Programming
Walking the program
• There are four ways to advance the program in gdb
• next (n) steps the program forward one statement
• step (s) moves the program forward one statement, but “steps into” a function
• continue (c) continues running the program from that point till it terminates or hits another breakpoint
CMPSC 311 – Introduction to Systems Programming
Walking the program
• There are four ways to advance the program in gdb • next (n), step (s), continue (c), … and
• finish (fin) continues until the function returns
CMPSC 311 – Introduction to Systems Programming
Putting it all together
#include
int factorial( int i ) {
assert( i>=0 ); // Breakpoint here if ( i == 1 ) {
return( 1 ); }
return( factorial(i-1)*i ); }
int main( int argc, char *argv[] ) {
if ( argc > 1 ) {
i = atoi(argv[1]);
printf( “Factorial of %d: %d\n”, i, factorial(i) ); // Breakpoint here return( 0 );
(gdb) b factorial
Breakpoint 1 at 0x6e5: file debugging.c, line 7. (gdb) b 20
Breakpoint 2 at 0x75a: file debugging.c, line 20. (gdb)
CMPSC 311 – Introduction to Systems Programming
Putting it all together
(gdb) run 3
Starting program: /root/project/debugging 3
Breakpoint 2, main (argc=2, argv=0x7fffffffe718) at debugging.c:20 20 printf(“Factorial of %d: %d\n “, i, factorial(i)); (gdb) c
Continuing.
Breakpoint 1, factorial (i=3) at debugging.c:7
7 (gdb) n 8 (gdb) n 11 (gdb) s
assert(i >= 0);
if (i <= 1) {
return (factorial(i - 1) * i);
int factorial( int i )
Breakpoint 1, factorial (i=2) at debugging.c:7 7 assert(i >= 0);
Continuing.
Breakpoint 1, factorial (i=1) at debugging.c:7
assert( i>=0 ); // Breakpoint here
if ( i == 1 ) {
return( 1 ); }
return( factorial(i-1)*i );
(gdb) c Continuing. Factorial of 3: 6
[Inferior 1 (process 417) exited normally] (gdb)
int main( int argc, char *argv[] )
if ( argc > 1 ) {
i = atoi(argv[1]);
printf( “Factorial of %d: %d\n”, i, factorial(i) ); // Breakpoint here return( 0 );
assert(i >= 0);
CMPSC 311 – Introduction to Systems Programming
Putting it all together
(gdb) run 3
Starting program: /root/project/debugging 3
Breakpoint 2, main (argc=2, argv=0x7fffffffe718) at debugging.c:20 20 printf(“Factorial of %d: %d\n “, i, factorial(i)); (gdb) c
Continuing.
Breakpoint 1, factorial (i=3) at debugging.c:7
7 (gdb) n 8 (gdb) n 11 (gdb) s
assert(i >= 0);
if (i <= 1) {
return (factorial(i - 1) * i);
int factorial( int i )
Breakpoint 1, factorial (i=2) at debugging.c:7 7 assert(i >= 0);
Continuing.
Breakpoint 1, factorial (i=1) at debugging.c:7
assert( i>=0 ); // Breakpoint here
if ( i == 1 ) {
return( 1 ); }
return( factorial(i-1)*i );
(gdb) c Continuing. Factorial of 3: 6
[Inferior 1 (process 417) exited normally] (gdb)
int main( int argc, char *argv[] )
if ( argc > 1 ) {
i = atoi(argv[1]);
printf( “Factorial of %d: %d\n”, i, factorial(i) ); // Breakpoint here return( 0 );
assert(i >= 0);
CMPSC 311 – Introduction to Systems Programming
Putting it all together
(gdb) run 3
Starting program: /root/project/debugging 3
Breakpoint 2, main (argc=2, argv=0x7fffffffe718) at debugging.c:20 20 printf(“Factorial of %d: %d\n “, i, factorial(i)); (gdb) c
Continuing.
Breakpoint 1, factorial (i=3) at debugging.c:7
7 (gdb) n 8 (gdb) n 11 (gdb) s
assert(i >= 0);
if (i <= 1) {
return (factorial(i - 1) * i);
int factorial( int i )
Breakpoint 1, factorial (i=2) at debugging.c:7 7 assert(i >= 0);
Continuing.
Breakpoint 1, factorial (i=1) at debugging.c:7
assert( i>=0 ); // Breakpoint here
if ( i == 1 ) {
return( 1 ); }
return( factorial(i-1)*i );
(gdb) c Continuing. Factorial of 3: 6
[Inferior 1 (process 417) exited normally] (gdb)
int main( int argc, char *argv[] )
if ( argc > 1 ) {
i = atoi(argv[1]);
printf( “Factorial of %d: %d\n”, i, factorial(i) ); // Breakpoint here return( 0 );
assert(i >= 0);
CMPSC 311 – Introduction to Systems Programming
Putting it all together
(gdb) run 3
Starting program: /root/project/debugging 3
Breakpoint 2, main (argc=2, argv=0x7fffffffe718) at debugging.c:20 20 printf(“Factorial of %d: %d\n “, i, factorial(i)); (gdb) c
Continuing.
Breakpoint 1, factorial (i=3) at debugging.c:7
7 (gdb) n 8 (gdb) n 11 (gdb) s
assert(i >= 0);
if (i <= 1) {
return (factorial(i - 1) * i);
int factorial( int i )
Breakpoint 1, factorial (i=2) at debugging.c:7 7 assert(i >= 0);
Continuing.
Breakpoint 1, factorial (i=1) at debugging.c:7
assert( i>=0 ); // Breakpoint here
if ( i == 1 ) {
return( 1 ); }
return( factorial(i-1)*i );
(gdb) c Continuing. Factorial of 3: 6
[Inferior 1 (process 417) exited normally] (gdb)
int main( int argc, char *argv[] )
if ( argc > 1 ) {
i = atoi(argv[1]);
printf( “Factorial of %d: %d\n”, i, factorial(i) ); // Breakpoint here return( 0 );
assert(i >= 0);
CMPSC 311 – Introduction to Systems Programming
Putting it all together
(gdb) run 3
Starting program: /root/project/debugging 3
Breakpoint 2, main (argc=2, argv=0x7fffffffe718) at debugging.c:20 20 printf(“Factorial of %d: %d\n “, i, factorial(i)); (gdb) c
Continuing.
Breakpoint 1, factorial (i=3) at debugging.c:7
7 (gdb) n 8 (gdb) n 11 (gdb) s
assert(i >= 0);
if (i <= 1) {
return (factorial(i - 1) * i);
int factorial( int i )
Breakpoint 1, factorial (i=2) at debugging.c:7 7 assert(i >= 0);
Continuing.
Breakpoint 1, factorial (i=1) at debugging.c:7
assert( i>=0 ); // Breakpoint here
if ( i == 1 ) {
return( 1 ); }
return( factorial(i-1)*i );
(gdb) c Continuing. Factorial of 3: 6
[Inferior 1 (process 417) exited normally] (gdb)
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com