Unformatted text preview:

IntroductionHigh-level strategyStrategy 1: Reading stack tracesIntroMeaningLast LineReading the stack trace backwardsPinpointing the problemTake-home lessonsStrategy 2: Debugging with print statementsExample 1: Case of the never-ending programBe liberal with prints, but not too liberalExample 2: Case of the empty messageDebuggingTake-away lessonsStrategy: 2 assertions are your friendExample: The case of the ill-formed messageWhat are the assumptions?Asserts to the rescueInstances and assertionsVerifying my assumptions: Part 1Verifying my assumptions: Part 2Take-away lessonsStrategy 4: Use YOUR own test casesStrategy 5: Using an industrial-strength (or at least, real) debuggerSome common sources of bugsModifying the index variable in a for loopUse "is not None" instead of "!= None"Writing your own code instead of relying on library functionsConclusionBitter Lessons from 6.02 Lab 1: A Guide to DebuggingKanak Kshetri(Edited by Hari Balakrishnan)September 17, 20101 IntroductionThe purpose of this guide is to show you some techniques to answer the immortal question:“Why isn’t my code working?”There are two levels of being wrong:1. Your code runs, but the result is incorrect.2. Your code doesn’t run at all.We’ll focus on the #2 to begin with.2 High-level strategy1. Figure out what the problem is.2. Figure out where the problem is coming from.3. Solve the problem.4. We discuss five strategies: reading stack traces, sprinkling print statements carefully,using assertions, writing your own test cases, and getting familiar with a real debugger.3 Strategy 1: Reading stack traces3.1 IntroA stack trace is the nasty thing that Python spits out when your code is incorrect and doesn’trun correctly. Here’s one from when I was doing Task #3 of Lab #1.Traceback ( most recent c a l l l a s t ) :F i l e " / af s / athena . mit . edu / user / k / a / kanak / 6 0 2 / lab1 / lab1_3 . py " ,l i n e 130 , in <module>rcvd_image = lab1 . b i t s _ t o _ f a r r a y ( r c v d_ bi ts )F i l e " / af s / athena . mit . edu / user / k / a / kanak / 6 0 2 / lab1 / lab1 . py " ,l i n e 111 , in b i t s _ t o _ f a r r a y1as s er t len ( b i t s ) % n b it s == 0 , " b i t s not a multiple o f %d"% nbi t sAssertionError : b i t s not a mu ltiple of 83.2 MeaningThe stack trace actually has a lot of useful information that can help you figure out what’swrong.3.2.1 Last Line• The AssertionError: bits not a multiple of 8 tells you what went wrong: some-where, the length of a list was supposed to be a multiple of 8, but it wasn’t in the codethat executed.• But you really want to know where exactly did things go awry?3.2.2 Reading the stack trace backwards• The line right above the Assertion Error (assert len(...)) tells you where it wentwrong.• But that line isn’t something I wrote!• Where is that line coming from?• If you look at the line in the trace above it, it tells you the filename (“lab1.py”) and theexact line number (“111”). It even tells you the function name (“bits_to_farray”)• But I didn’t write anything in lab1.py...• Let’s keep going upwards.• The line above tells us that line 130 in lab1_3.py, is where the problem started.• So rcvd_bits, which is the result of my receive function, is not a multiple of 8.3.2.3 Pinpointing the problem• Now, I know what the problem is (I dropped some bits or added extra ones, because Idon’t have a multiple of 8), and I know where the problem is (somewhere in the receivefunction).• I can now start looking at the places where I’m adding or removing things from my listto find the culprit.3.3 Take-home lessons• Read the last line of a stack trace to find out the error• Work your way backwards till you find the place in your code that caused the mistake.24 Strategy 2: Debugging with print statementsDebugging with print statements is usually a very good idea, not only to figure out why thingsaren’t running, but (often) more importantly to figure out why the results aren’t being producedcorrectly.4.1 Example 1: Case of the never-ending program• Suppose you’re working on lab1_4, and for some reason the program just doesn’t termi-nate.• To add to your troubles, you have decided to write a mammoth 50+ line function called“receive” that does everything from digitizing to doing the modulo decoding to findingsync. (It is, in most cases, a bad idea to have functions that are longer than one screenin length.)• Now which part of the function could be causing the problem?4.1.1 Be liberal with prints, but not too liberal• Add a print statement to the start of the function so that we know your function is beingcalled.• Examples of places where print statements may provide insight:– "Entering receive"– "Entering receive, sample length: "• Examples of what not to print because they don’t tell you the context.– "hello"– "hi"– "asdfasda"• Add a print statement to the end of your function that says something like "Exitingreceive" so you know when your function is done.• Now add a print statement in between each “component”:– before and after digitizing– before and after doing modulo– before and after sync• Ideally, each of these components would be a seperate function, but we have seen somecases of large monolithic functions being written by students (bad idea!).• Run your program.• You should see when each component runs. . . this will give you an idea about where thefunction is spending most of its time.34.2 Example 2: Case of the empty message• You’re still working on lab1_4, and now your program returns, but it’s always returningan empty list.• What could the problem be?• There are a lot of places where you’re fooling around with the message: digitizing, modulodecoding, finding syncs etc.• Let’s find out what the message length is before and after each of these steps.4.2.1 Debugging• Add a print statement right after the function is called. . . print "Length of originalsignal: ", len(samples)• Add a print statement before and after you do anything to it.• Remember to give it a useful label (e.g. "Length of signal after digitizing: ") andnot just print len(samples). . . . You don’t want to get 10 numbers out and have no ideawhat each number means.4.3 Take-away lessons• Adding print statements at strategic locations can help you better understand which partof a function is the culprit. But don’t overdo the printing, you will be overwhelmed!•


View Full Document

MIT 6 02 - A Guide to Debugging

Download A Guide to Debugging
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view A Guide to Debugging and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view A Guide to Debugging 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?