Debugging! The material for this lecture is drawn, in part, from! The Practice of Programming (Kernighan & Pike) Chapter 5!

Similar documents
Debugging! The material for this lecture is drawn, in part, from! The Practice of Programming (Kernighan & Pike) Chapter 5!

Debugging (Part 1) The material for this lecture is drawn, in part, from The Practice of Programming (Kernighan & Pike) Chapter 5

Princeton University Computer Science 217: Introduction to Programming Systems. Building Multi-File Programs with the make Tool

Debugging (Part 2) 1

Princeton University Computer Science 217: Introduction to Programming Systems. Data Structures

Class Information ANNOUCEMENTS

CS 261 Fall C Introduction. Variables, Memory Model, Pointers, and Debugging. Mike Lam, Professor

Princeton University COS 217: Introduction to Programming Systems GDB Tutorial and Reference

CSE 374 Programming Concepts & Tools. Brandon Myers Winter 2015 Lecture 11 gdb and Debugging (Thanks to Hal Perkins)

Princeton University Computer Science 217: Introduction to Programming Systems Program and Programming Style

We first learn one useful option of gcc. Copy the following C source file to your

PRINCIPLES OF OPERATING SYSTEMS

Performance improvement techniques & tools. Everything should be built top-down, except the first time. -

12. Debugging. Overview. COMP1917: Computing 1. Developing Programs. The Programming Cycle. Programming cycle. Do-it-yourself debugging

Lecture 7: file I/O, more Unix

CS2141 Software Development using C/C++ Debugging

Problem Set 1: Unix Commands 1

C Introduction. Comparison w/ Java, Memory Model, and Pointers

Introduction to C. Ayush Dubey. Cornell CS 4411, August 31, Geared toward programmers

CSC209H Lecture 3. Dan Zingaro. January 21, 2015

Introduction to C. Robert Escriva. Cornell CS 4411, August 30, Geared toward programmers

Testing! The material for this lecture is drawn, in part, from! The Practice of Programming (Kernighan & Pike) Chapter 6!

Introduction to C. Zhiyuan Teo. Cornell CS 4411, August 26, Geared toward programmers

Testing! The material for this lecture is drawn, in part, from! The Practice of Programming (Kernighan & Pike) Chapter 6!

o Code, executable, and process o Main memory vs. virtual memory

Introduction to C. Sean Ogden. Cornell CS 4411, August 30, Geared toward programmers

Laboratory 1 Semester 1 11/12

CSE 374 Programming Concepts & Tools

CSE 303: Concepts and Tools for Software Development

CSCI0330 Intro Computer Systems Doeppner. Lab 02 - Tools Lab. Due: Sunday, September 23, 2018 at 6:00 PM. 1 Introduction 0.

ECE/ME/EMA/CS 759 High Performance Computing for Engineering Applications

Program Verification! Goals of this Lecture! Words from the Wise! Testing!

Running a C program Compilation Python and C Variables and types Data and addresses Functions Performance. John Edgar 2

COSC Software Engineering. Lecture 16: Managing Memory Managers

Outline. Computer programming. Debugging. What is it. Debugging. Hints. Debugging

EL2310 Scientific Programming

EL2310 Scientific Programming

C programming basics T3-1 -

18-600: Recitation #3

Princeton University COS 217: Introduction to Programming Systems Emacs Reference and Tutorial

Slide Set 8. for ENCM 339 Fall 2017 Section 01. Steve Norman, PhD, PEng

CS 11 C track: lecture 5

NEXT SET OF SLIDES FROM DENNIS FREY S FALL 2011 CMSC313.

Programming in C in a UNIX environment

CMSC 313 COMPUTER ORGANIZATION & ASSEMBLY LANGUAGE PROGRAMMING

In Java we have the keyword null, which is the value of an uninitialized reference type

CS61 Lecture II: Data Representation! with Ruth Fong, Stephen Turban and Evan Gastman! Abstract Machines vs. Real Machines!

Lectures 5-6: Introduction to C

Beyond this course. Machine code. Readings: CP:AMA 2.1, 15.4

Princeton University COS 333: Advanced Programming Techniques A Subset of C90

ch = argv[i][++j]; /* why does ++j but j++ does not? */

Debugging. ICS312 Machine-Level and Systems Programming. Henri Casanova

Lab 1 Introduction to UNIX and C

Parameter passing. Programming in C. Important. Parameter passing... C implements call-by-value parameter passing. UVic SEng 265

For Your Amusement. Beware of bugs in the above code; I have only proved it correct, not tried it. Donald Knuth. Program Verification

CSE 303 Lecture 8. Intro to C programming

[0569] p 0318 garbage

GDB Tutorial. A Walkthrough with Examples. CMSC Spring Last modified March 22, GDB Tutorial

C for C++ Programmers

System Assertions. Andreas Zeller

Programming Tools. Venkatanatha Sarma Y. Lecture delivered by: Assistant Professor MSRSAS-Bangalore

CSCI-1200 Data Structures Spring 2016 Lecture 6 Pointers & Dynamic Memory

MPATE-GE 2618: C Programming for Music Technology. Unit 4.1

High-performance computing and programming Intro to C on Unix/Linux. Uppsala universitet

Getting started with UNIX/Linux for G51PRG and G51CSA

Short Notes of CS201

EL2310 Scientific Programming

EE 209: Programming Structures for Electrical Engineering

CSE 12 Spring 2016 Week One, Lecture Two

Programming. Pointers, Multi-dimensional Arrays and Memory Management

Programming Tips for CS758/858

INITIALISING POINTER VARIABLES; DYNAMIC VARIABLES; OPERATIONS ON POINTERS

CS201 - Introduction to Programming Glossary By

ECEN 449 Microprocessor System Design. Review of C Programming. Texas A&M University

Lecture 3. More About C

CA31-1K DIS. Pointers. TA: You Lu

Week 3. This is CS50. Harvard University. Fall Cheng Gong

CS201 Lecture 2 GDB, The C Library

Memory Allocation in C C Programming and Software Tools. N.C. State Department of Computer Science

Programming in the Large Steps

Lectures 5-6: Introduction to C

CSE 12 Spring 2018 Week One, Lecture Two

Computer Programming: Skills & Concepts (CP) Files in C

Exercise 1: Basic Tools

Computer Labs: Debugging

Motivation was to facilitate development of systems software, especially OS development.

Lecture 07 Debugging Programs with GDB

C - Basics, Bitwise Operator. Zhaoguo Wang

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #17. Loops: Break Statement

CS113: Lecture 7. Topics: The C Preprocessor. I/O, Streams, Files

Programming in C First meeting

Lecture 9 Assertions and Error Handling CS240

Scientific Programming in C IX. Debugging

CSC 1600 Memory Layout for Unix Processes"

File Access. FILE * fopen(const char *name, const char * mode);

The Valgrind Memory Checker. (i.e., Your best friend.)

Motivation was to facilitate development of systems software, especially OS development.

1. Allowed you to see the value of one or more variables, or 2. Indicated where you were in the execution of a program

Recitation: Cache Lab & C

Goals of this Lecture

Transcription:

Debugging The material for this lecture is drawn, in part, from The Practice of Programming (Kernighan & Pike) Chapter 5 1 Goals of this Lecture Help you learn about: Strategies and tools for debugging your code Why? Debugging large programs can be difficult A power programmer knows a wide variety of debugging strategies A power programmer knows about tools that facilitate debugging Debuggers Version control systems 2 1

Testing vs. Debugging Testing What should I do to try to break my program? or Is there a problem? Debugging What should I do to try to fix my program? or There is a problem. 3 Debugging Observations Most bugs are reproducible Focus of inspection can be narrowed Bugs are mismatches between expectation & execution Can add more checks on expectations Program flow can be watched Printing & logging (especially high-volume) Source-level debugging Not all bugs are visibly manifested Classic cause of the bug just went away Nothing ever just goes away in a deterministic world 4 2

Debugging Heuristics Debugging Heuristic When Applicable (1) Understand error messages Build-time (2) Think before writing (3) Look for familiar bugs (4) Divide and conquer Run-time (5) Add more internal tests (6) Write output (7) Use a debugger (8) Focus on recent changes 5 Understand Error Messages (cont.) Debugging at build-time is easier than debugging at runtime, if and only if you (1) Understand the error messages #include <stdioo.h> int main(void) /* Print "hello, world" to stdout and return 0. { printf("hello, world\n"); return 0; } Which tool (preprocessor, compiler, or linker) reports the error(s)? $ gcc217 hello.c -o hello hello.c:1:20: stdioo.h: No such file or directory hello.c:3:1: unterminated comment hello.c:2: error: syntax error at end of input 6 3

Understand Error Messages (cont.) #include <stdio.h> int main(void) /* Print "hello, world" to stdout and return 0. */ { printf("hello, world\n"); retun 0; } Which tool (preprocessor, compiler, or linker) reports the error(s)? $ gcc217 hello.c -o hello hello.c: In function `main': hello.c:7: error: `retun' undeclared (first use in this function) hello.c:7: error: (Each undeclared identifier is reported only once hello.c:7: error: for each function it appears in.) hello.c:7: error: syntax error before numeric constant 7 Understand Error Messages (cont.) #include <stdio.h> int main(void) /* Print "hello, world" to stdout and return 0. */ { prinf("hello, world\n"); return 0; } Which tool (preprocessor, compiler, or linker) reports the error(s)? $ gcc217 hello.c -o hello hello.c: In function `main': hello.c:6: warning: implicit declaration of function `prinf' /tmp/cc43ebjk.o(.text+0x25): In function `main': : undefined reference to `prinf' collect2: ld returned 1 exit status 8 4

Think Before Writing Inappropriate changes could make matters worse, so (2) Think before writing Draw pictures of the data structures Take a break Sleep on it Start early so you can Explain the code to: Yourself Someone else A teddy bear A giant wookie 9 (3) Look for Familiar Bugs Some favorites: switch (i) { case 0: break; case 1: case 2: } int i; scanf("%d", i); char c; c = getchar(); while (c = getchar() = EOF) if (i = 5) if (i & j) What are the errors? 10 5

(3) Look for Familiar Bugs (cont.) Loop start & end conditions à off by 1 errors Most loop iterations run just fine Copied & pasted code Check scoping, re-use of variables Compiler complains about uninitialized use, not re-use 11 Divide and Conquer (4) Divide and conquer: input data Incrementally find smallest/simplest input that illustrates the bug Example: Program fails on large input file filex Approach 1: Remove input Start with filex Incrementally remove lines of filex until bug disappears Maybe in binary search fashion Approach 2: Add input Start with small subset of filex Incrementally add lines of filex until bug appears 12 6

Divide and Conquer (cont.) (4) Divide and conquer: code Incrementally find smallest code subset that illustrates the bug Example: Test client for your module fails Approach 1: Remove code Start with test client Incrementally remove lines of test client until bug disappears Approach 2: Add code Start with minimal client Incrementally add lines of test client until bug appears 13 (5) Add More Internal Tests Internal tests help find bugs (recall Testing ) Internal test also can help eliminate bugs Checking invariants and conservation properties can eliminate some functions from the bug hunt 14 7

(6) Write Output Print values of important variables at critical spots Poor: printf("%d", keyvariable); Maybe better: printf("%d\n", keyvariable); Better: printf("%d", keyvariable); fflush(stdout); stdout is buffered; program may crash before output appears Printing '\n' flushes the stdout buffer, but not if stdout is redirected to a file Call fflush() to flush stdout buffer explicitly 15 (6) Write Output (cont.) Maybe even better: fprintf(stderr, "%d", keyvariable); Maybe better still: Write debugging output to stderr; debugging output can be separated from normal output via redirection Bonus: stderr is unbuffered FILE *fp = fopen("logfile", "w"); fprintf(fp, "%d", keyvariable); fflush(fp); Write to a log file 16 8

Use a Debugger Alternative to displaying output Bonuses: Debugger can load core dumps Examine state of program when it terminated Debugger can attach to a running program 17 The GDB Debugger GNU Debugger Part of the GNU development environment Integrated with Emacs editor Allows user to: Run program Set breakpoints Step through code one line at a time Examine values of variables during run Etc. See Appendix 1 for details 18 9

Focus on Recent Changes (8) Focus on recent changes Corollary: Debug now, not later Difficult: (1) Write entire program (2) Test entire program (3) Debug entire program Easier: (1) Write a little (2) Test a little (3) Debug a little (4) Write a little (5) Test a little (6) Debug a little 19 Focus on Recent Changes (cont.) (8) Focus on recent change (cont.) Corollary: Maintain old versions Difficult: (1) Change code (2) Note bug (3) Try to remember what changed since last working version Easier: (1) Backup working version (2) Change code (3) Note bug (4) Compare code with working version to determine what changed 20 10

Maintaining Previous Versions To maintain old versions Approach 1: Manually copy project directory $ mkdir myproject $ cd myproject Create project files here. $ cd.. $ cp r myproject myprojectdatetime $ cd myproject Continue creating project files here. Approach 1.5: use snapshot support in filesystem Approach 2: Use RCS 21 RCS Revision Control System A simple personal version control system Provided with many Linux distributions Available on nobel Allows developer to: Create a source code repository Check source code files into repository RCS saves old versions Check source code files out of repository Appropriate for one-developer projects Not appropriate for multi-developer projects Use CVS or Subversion instead See Appendix 2 for details 22 11

Summary Debugging Heuristic When Applicable (1) Understand error messages Build-time (2) Think before writing (3) Look for familiar bugs (4) Divide and conquer Run-time (5) Add more internal tests (6) Write output (7) Use a debugger * (8) Focus on recent changes ** * Use GDB ** Use RCS 23 Appendix 1: Using GDB An example program File testintmath.c: #include <stdio.h> int gcd(int i, int j) { int temp; while (j = 0) { temp = i % j; i = j; j = temp; } return i; } int lcm(int i, int j) { return (i / gcd(i, j)) * j; } Euclid s algorithm; Don t be concerned with details int main(void) { int igcd; int ilcm; igcd = gcd(8, 12); ilcm = lcm(8, 12); printf("%d %d\n", igcd, ilcm); return 0; } The program is correct But let s pretend it has a runtime error in gcd() 24 12

Appendix 1: Using GDB (cont.) General GDB strategy: Execute the program to the point of interest Use breakpoints and stepping to do that Examine the values of variables at that point 25 Appendix 1: Using GDB (cont.) Typical steps for using GDB: (1) Build with g gcc217 g testintmath.c o testintmath Adds extra information to executable file that GDB uses (2) Run Emacs, with no arguments emacs (3) Run GDB on executable file from within Emacs <Esc key> x gdb <Enter key> testintmath <Enter key> (4) Set breakpoints, as desired break main GDB sets a breakpoint at the first executable line of main() break gcd GDB sets a breakpoint at the first executable line of gcd() 26 13

Appendix 1: Using GDB (cont.) Typical steps for using GDB (cont.): (5) Run the program run GDB stops at the breakpoint in main() Emacs opens window showing source code Emacs highlights line that is to be executed next continue GDB stops at the breakpoint in gcd() Emacs highlights line that is to be executed next (6) Step through the program, as desired step (repeatedly) GDB executes the next line (repeatedly) Note: When next line is a call of one of your functions: step command steps into the function next command steps over the function, that is, executes the next line without stepping into the function 27 Appendix 1: Using GDB (cont.) Typical steps for using GDB (cont.): (7) Examine variables, as desired print i print j print temp GDB prints the value of each variable (8) Examine the function call stack, if desired where GBB prints the function call stack Useful for diagnosing crash in large program (9) Exit gdb quit (10) Exit Emacs <Ctrl-x key> <Ctrl-c key> 28 14

Appendix 1: Using GDB (cont.) GDB can do much more: Handle command-line arguments run arg1 arg2 Handle redirection of stdin, stdout, stderr run < somefile > someotherfile Print values of expressions Break conditionally Etc. See Programming with GNU Software (Loukides and Oram) Chapter 6 29 Appendix 2: Using RCS Typical steps for using RCS: (1) Create project directory, as usual mkdir helloproj cd helloproj (2) Create RCS directory in project directory mkdir RCS RCS will store its repository in that directory (3) Create source code files in project directory emacs hello.c (4) Check in ci hello.c Adds file to RCS repository Deletes local copy (don t panic) Can provide description of file (1 st time) Can provide log message, typically describing changes 30 15

Appendix 2: Using RCS (cont.) Typical steps for using RCS (cont.): (5) Check out most recent version for reading co hello.c Copies file from repository to project directory File in project directory has read-only permissions (6) Check out most recent version for reading/writing co l hello.c Copies file from repository to project directory File in project directory has read/write permissions (7) List versions in repository rlog hello.c Shows versions of file, by number (1.1, 1.2, etc.), with descriptions (8) Check out a specified version co l rversionnumber hello.c 31 Appendix 2: Using RCS (cont.) RCS can do much more: Merge versions of files Maintain distinct development branches Place descriptions in code as comments Assign symbolic names to versions Etc. See Programming with GNU Software (Loukides and Oram) Chapter 8 Recommendation: Use RCS ci and co can become automatic 32 16

Appendix 3: Debugging Mem Mgmt Some debugging techniques are specific to dynamic memory management That is, to memory managed by malloc(), calloc(), realloc(), and free() Soon will be pertinent in the course For future reference 33 Appendix 3: Debugging Mem Mgmt (cont.) (9) Look for familiar dynamic memory management bugs Some of our favorites: int *p; /* value of p undefined */ *p = somevalue; int *p; /* value of p undefined */ fgets(p, 1024, stdin); Dangling pointer Dangling pointer int *p; p = (int*)malloc(sizeof(int)); free(p); *p = 5; Dangling pointer 34 17

Appendix 3: Debugging Mem Mgmt (cont.) (9) Look for familiar dynamic memory management bugs (cont.) Some of our favorites (cont.): int *p; p = (int*)malloc(sizeof(int)); p = (int*)malloc(sizeof(int)); Memory leak alias Garbage creation Detection: Valgrind, etc. int *p; p = (int*)malloc(sizeof(int)); free(p); free(p); Multiple free Detection: man malloc, MALLOC_CHECK_ 35 Appendix 3: Debugging Mem Mgmt (cont.) (9) Look for familiar dynamic memory management bugs (cont.) Some of our favorites (cont.): char *s1 = "Hello"; char *s2; s2 = (char*)malloc(strlen(s1)); strcpy(s2, s1); char *s1 = "Hello"; char *s2; s2 = (char*)malloc(sizeof(s1)); strcpy(s2, s1); Allocating too few bytes Allocating too few bytes double *p; p = (double*)malloc(sizeof(double*)); Allocating too few bytes 36 18

Appendix 3: Debugging Mem Mgmt (cont.) (10)Segmentation fault? Make it happen within gdb, and then issue the gdb where command. The output will lead you to the line that caused the fault. (But that line may not be where the error resides.) (11)Call assert() to make sure value returned by malloc(), calloc(), and realloc() is not NULL. (12)Manually inspect each call of malloc(), calloc(), and realloc() in your code, making sure that it allocates enough memory. (13)Temporarily hardcode each call of malloc(), calloc(), and realloc() such that it requests a large number of bytes. If the error disappears, then you'll know that at least one of your calls is requesting too few bytes. 37 Appendix 3: Debugging Mem Mgmt (cont.) (14) Temporarily comment-out each call of free() in your code. If the error disappears, then you'll know that you're freeing memory too soon, or freeing memory that already has been freed, or freeing memory that should not be freed, etc. (15)Use the Meminfo tool. Programs built with gcc217m are much more sensitive to dynamic memory management errors than are programs built with gcc217. So the error might manifest itself earlier, and thereby might be easier to diagnose. 38 19