Debugging Techniques - PowerPoint PPT Presentation

1 / 37
About This Presentation
Title:

Debugging Techniques

Description:

Annatala Wolf. 222 Supplemental Lecture. Bugs Stop Programs (and lolcats) From Working ... You cannot fix the error if you don't know roughly where it is! ... – PowerPoint PPT presentation

Number of Views:1684
Avg rating:3.0/5.0
Slides: 38
Provided by: awo4
Category:

less

Transcript and Presenter's Notes

Title: Debugging Techniques


1
Debugging Techniques
  • Annatala Wolf
  • 222 Supplemental Lecture

2
Most of the art of programming is debugging
  • Bugs are always present in large applications.
  • The majority of a softwares life cycle is in the
    support phase, so debugging saves big money!

3
Bugs can be expensive and difficult to find
4
The Most Important Rule
  • If youre lost or confused, randomly changing
    things around in code will not help
  • You cannot fix the error if you dont know
    roughly where it is!
  • Errors can only be caught and fixed by debugging
    in a systematic fashion

5
Fortunate News
  • There are a lot of bugs in C that are extremely
    hard, or even impossible to find.
  • I worked in industry for a year with a DoD
    contractor we spent all year looking for a
    three-year-old memory leak we never found
  • However, Resolve/C prevents the
    worst-of-the-worst errors by limiting pointers
    to Kernels. To move objects around, we use
    instead (which is always safe).

6
Typical Debugging
  • Usually, you will do debugging in an IDE
    (Integrated Development Environment) that has
    debug features like breakpoints (places you
    pause the program, and can run it line by
    line), watches (variables you track as the
    program runs), and other neat tools.
  • There are also tools you can run separately as
    your code runs, i.e. a tool to find memory leaks
  • You dont get this stuff in emacs the way we have
    it set up. ? So you must use strategy.

7
Real Programmers Use
xkcd.com
8
emacs Is Hard To Learn
  • Regrettably, emacs is the only editor we can set
    up to work with Resolve/C in the UNIX system
    where we (securely) keep the code.

9
The Unix System
  • Many students have no problems with coding, but
    using Unix, Solaris, and emacs proves challenging
    (and extremely annoying)
  • Part of your job as a computer scientist will
    always involve working with unfamiliar systems
    that dont perform as expected, so youll have to
    get used to it
  • The challenge is to learn only what you need to
    perform the tasks at hand

10
Basic Unix Commands
  • cd directory
  • change directories (use .. for previous
    directory, or for home directory)
  • ls l
  • long list of all files, including permissions,
    etc.
  • cp source destination
  • copy file (to move files, use mv instead)
  • mkdir name
  • make a new directory
  • rm filename
  • delete a file

11
Other Unix Commands
  • less textfilename
  • print the contents of a text file to the screen
  • chmod 777 filename
  • set a files permissions so it can be read, be
    written, and be executed by anyone (in case you
    cant access or execute a needed file, try this)
  • rcpp-make
  • compile all Resolve/C files in the current
    directory
  • dos2unix textfilename
  • convert \r to \n in a text file, so it works
    in Unix
  • (use unix2dos for the opposite effect)

12
Unix Redirects
  • If you successfully compile Example.cpp, it will
    make an executable file (one you can run) called
    Example
  • To run Example, just type the name
  • Example
  • To redirect standard in to in.txt, add lt in.txt
    at the end
  • Example lt in.txt
  • To redirect standard out to out.txt, add gt
    out.txt
  • Example gt out.txt
  • To automatically overwrite out.txt if it
    exists, use gt!
  • Example gt! out.txt
  • To do this with both input and output, include
    both options
  • Example lt in.txt gt! out.txt

13
Handout Clues
  • Usually the Lab handout will contain all the
    information you need to navigate the UNIX system.
  • If youre having trouble compiling or testing
    your code, look to the handout first
  • If youre not certain what the requirements are
    for a correct implementation, the handout should
    give you a detailed description of the
    requirements
  • Sometimes it may help to look at an old handout,
    such as the one from Closed Lab 1 (i.e., you
    wont be able to compile if you havent run
    getsetup)

14
Kinds of Errors
  • There are many kinds of errors you may find in
    your code. Here are some well discuss
  • Makefile Mischief
  • Compile-Time Errors
  • Type Errors (can be compile-time or runtime)
  • Violated Assertions
  • Program Crash
  • Infinite Loop
  • Unexpected Behavior

15
Makefile Mischief
  • Makefile.rcpp is a small file the compiler
    creates any time you compile code. It tells the
    compiler which files are up to date, so it wont
    recompile things that havent changed.
  • If you copy files to and from your account, the
    Makefile might become outdated. The compiler
    might seem to work, but changes arent being
    reflected. Or, you get odd linking errors.
  • When in doubt, delete the makefile and recompile.
    This compiles everything fresh.

16
Reading Error Messages
  • For any kind of error that produces an error
    message (syntax, violated assertion, or crash),
    the first strategy to fixing the error is to
    carefully examine the message.
  • Always check the top of the error message and
    read down until you find something useful.
  • Because of the way we use templates, there may be
    paragraphs of template code telling you what was
    instantiated where. You have to keep looking
    until you find the first thing that looks like a
    description of an error, rather than a template
    instantiation.

17
Compile-Time Errors
  • Most compile-time errors are easy to catch, and
    easy to fix. You need to know how to do this by
    now, so dont expect more than 1/5 on a lab
    unless it at least compiles.
  • Some errors may be masked by the fact that they
    dont cause a problem until later in your code.
    Example a missing brace may not be caught by the
    compiler until it notices code appearing in
    illegal places as a result later on.
  • Take heart a compile-time error will always be
    found either at the location it is caught, or
    earlier. (For mysterious errors, check for
    matching braces and parentheses.)

18
Commenting Out Code
  • One fast way to find compile-time errors in a
    crappy IDE like emacs is to comment code out. To
    do this, use // to turn lines of code into
    comments. If the error disappears, it must be in
    the sections you commented out!
  • Make sure you comment out either single lines, or
    entire blocks (if you choose to comment out an
    opening brace, you have to comment out the block
    and closing brace and vice versa).
  • If you comment out the body of a function, you
    may need to at least add a dummy return statement
    with an object of the correct type so that the
    function will compile.

19
Quick Error Finding
  • If you comment code out, you should be able to
    isolate compile-time errors very quickly, since
    each time you do it you can halve the space where
    the error must be. This works with all
    compile-time errors (syntax and type errors).
  • This method is called a binary search, and its
    fast! (Well discuss binary searches later.)
  • You can use a similar strategy to correct syntax
    try several bits of code to figure out which
    works.

20
Type Errors
  • These are usually caught at compile-time, but due
    to template use in C, its possible to see them
    at runtime in rare cases.
  • Usually type error messages contain template crap
    galore. Scan from the top down carefully.
  • Type mismatch errors will look something like
  • cannot convert foo to bar in SomeFunction()
  • bar expected where foo found
  • no foo exists for type bar
  • type mismatch from foo to bar.

21
Locating Type Errors
  • Type errors happen when you try to use a variable
    of one type as though it is another type (a type
    mismatch), or try to use an operation that
    doesnt exist (maybe you called it off the wrong
    type, or typed the name wrong).
  • If its a type mismatch, the message tells what
    two types caused the errorthe found type, and
    the one it expected to find.
  • A type error should also have the exact location,
    within one line. If it refers to an error in an
    argument passed to an operation, look for the
    line the operation was called from, not the
    location of the operation it was calling.

22
Runtime Errors
  • The call stack is the stack of operations that
    have been called while the program is running,
    which have not yet completed. This is printed
    out in some form for most runtime errors
  • 1 main()
  • 2 Recurse()
  • 3 Recurse()
  • 4 Helper()
  • The bottom of the call stack is the place the
    error was caught. Here, an error was caught in
    Helper(). (That doesnt mean thats where the
    error actually is, but its a good place to
    start.)

23
Debugging Runtime Errors
  • First strategy carefully read the error
  • Second strategy use debug statements
  • use them to isolate flow of control
  • use them to peek at variables
  • Third strategy write test code
  • Isolate errors to an operation by writing code
    that tests only a single operation. Confirm each
    operation works, one at a time.

24
Using Debug Statements
  • Debug statements can reveal two things where you
    are in code, and the value of a variable at a
    given point. To use them, put something like
    this in code
  • debug (Loop in foo(), x value ltlt x)
  • When the debug line runs, it outputs to standard
    error (the monitor, by default), similar to the
    code below
  • object Character_OStream error
  • error.Open_External()
  • error ltlt Loop in foo(), x value ltlt x
  • error.Close_External()

25
How Debug Works
  • Debug statements are useful because you can use
    them even if standard out is redirected. Also,
    you can compile code so it will remove them from
    the finished product.
  • To use them properly, you need to put in
    information about what part of code is running.
    This lets you isolate the flow-of-control (the
    order in which statements run, and which
    statements run at all).

26
Quick Debugging
  • You can also use debug to peek at variables that
    can be sent to output (the five basic Resolve
    data types).
  • Just be sure you include where the debug
    statement is in your code, otherwise you wont be
    able to tell two debug statements apart.
  • Like commenting out code, you can narrow down
    flow-of-control issues very rapidly (halving the
    possible location of a flow problem each time you
    test).

27
Debugging Collections
  • If youre the client of a collection object, you
    may want to see whats inside it.
  • It can be extremely helpful to create a helper
    operation that outputs (using debug statements)
    an entire collection you want to look at, while
    preserving it. (Note that you cant simply send,
    e.g., a Set object to output.)
  • You can also do this inside a Kernel to peek at
    the fields of self, but it can be tricky to not
    change the state of the Representation if those
    fields include collections or complex objects.

28
Violated Assertions
  • Violated assertions are good! They are among the
    easiest errors to locate and fix.
  • Violated assertions tell you exactly what
    requires clause you broke, and which operation
    you were in when you made the bad call.
  • The only time violated assertions are not easy to
    fix is when the underlying error is a logical
    error from something you did to screw up the
    Representation of a Kernel. In this case, the
    error might be that you screwed things up a long
    time ago, and only see the problem now.

29
Violated Assertion Sample
  • 0 main
  • 1 Some_Stuff()
  • 2 Do_Stuff(Partial_Map_Text_To_Text)
  • 3 Textoperator(Integer)
  • Violated assertion at
  • File /class/sce/rcpp-2007/RESOLVE_Foundation/Text
    /Text.cpp
  • Line 526
  • Operation operator
  • Violated assertion is
  • pos lt self

general location the bad call was made
operation whose contract we violated like a
red-headed stepchild from Mayberry
where Texts assertion is located not useful
to us
the part of the contract for Texts we
violated (this description is what was supposed
to be true, but was false)
30
Wait, I didnt write that!
  • In Lab 4, we write the Kernel operation Define()
    for you, and you write the rest.
  • Then students say Why did Define() trip an
    assertion? Didnt you guys write that?
  • The reason this can happen is the checker for
    Define() will call your Is_Defined() to do its
    work! So if it breaks, its probably breaking in
    your Is_Defined(), or in a local operation it
    calls.
  • Or, maybe you messed up the Representation.

31
Other Code Confusion
  • Some of the test code we give you for Kernels
    will feature operations like Put_To(), to output
    the collection. But if your labs not already
    perfect, Put_To() might break.
  • Why? Think about how we had to write Put_To() as
    a client of Set. It would need to call
    constructor, Remove_Any(x), Size(), Add(x), and
    the checker for Add(x) will call
    Is_Member(x) and there may even be local
    operations called by some of these.

32
Changing Concrete State
  • When white-box testing a Kernel (using what you
    know about how the Kernel is implemented to
    design smarter test cases), be extra careful.
    Even if Put_To() works and preserves the object,
    it may change how the object is represented
    inside, so you might see unexpected results.
  • Just think about what Put_To() must do as a
    client of your object, to figure it out.

33
Program Crash
  • A program can crash for other reasons
  • division by zero error
  • I/O error
  • ice cream dumped onto motherboard error
  • species-based hatred for ugly-bag-of-mostly-water
  • Look at the error carefully. Use debug
    statements to figure out when and where the crash
    happens.
  • When and where is more important than why!
  • some errors can be fixed even if you dont
    understand why its an error welcome to the art
    of programming ?

34
Infinite Loop
  • Does your computer seem to have frozen? You
    probably have an infinite while() loop.
  • For recursion, you get a heap overflow or
    segmentation fault error instead (because you
    will use up the memory in the program stack).
  • The cure check your while loops to make sure the
    change condition is occurring
  • Use debug statements to find the while loop that
    isnt stopping
  • Use debug statements to check loop conditions

35
Unexpected Behavior
  • This is usually the hardest problem to fix, as
    you get no error message the only error is bad
    output or bad results. The best approach is to
    debug specific cases.
  • Sometimes you end up seeing a violated assertion
    during testing, but it has to do with something
    unrelated you did wrong a long time ago. The
    only cure for this is to test each operation
    independently of the others.
  • In Kernels this is tricky, but still possible

36
Instructor and Grader
  • Dont hesitate to ask us if youre lost.
  • If you can figure it out yourself, though, youll
    probably do it a lot quicker than we can, and
    youll improve your ability to find errors.
  • If you have a general problem, include your code
    so I can look at it. (Id prefer it included as
    a plain, attached text file in email.)
  • If you have a specific error, also send me the
    error exactly as it appears (and the test case,
    for runtime errors). I can teach you to read it
    so you will learn more from the experience.

37
Summary
  • Debugging is essential to programming. Most
    systems have more debugging options than what you
    must use. I empathize with you.
  • However, with debug statements and comments there
    is literally no Resolve/C error in this class
    that you cant isolate and fix.
  • When in doubt, dont guess. Guessing makes
    finding errors an intractable problem. Use
    systematic methods to find the errors instead.
  • Dont be afraid to ask us (or your fellow
    classmates!) for debugging help.
Write a Comment
User Comments (0)
About PowerShow.com