How to debug small programs

One of the most frequent categories of bad questions I see on StackOverflow is:

I wrote this program for my assignment and it doesn’t work.
[20 lines of code].

And… that’s it.

If you’re reading this, odds are good it’s because I or someone else linked here from your StackOverflow question shortly before it was closed and deleted. (If you’re reading this and you’re not in that position, consider leaving your favourite tips for debugging small programs in the comments.)

StackOverflow is a question-and-answer site for specific questions about actual code; “I wrote some buggy code that I can’t fix” is not a question, it’s a story, and not even an interesting story. “Why does subtracting one from zero produce a number that is larger than zero, causing my comparison against zero on line 12 to incorrectly become true?” is a specific question about actual code.

So you’re asking the Internet to debug a broken program that you wrote. You’ve probably never been taught how to debug a small program, because let me tell you, what you’re doing now is not an efficient way to get that problem solved. Today is a good day to learn how to debug things for yourself, because StackOverflow is not about to debug your programs for you.

I’m going to assume that your program actually compiles but its action is wrong, and that moreover, you have a test case that shows that it is wrong. Here’s how to find the bug.

First, turn on all compiler warnings. There is no reason why a 20 line program should produce even a single warning. Warnings are the compiler telling you “this program compiles but does not do what you think it does”, and since that is precisely the situation you are in, it behooves you to pay attention to those warnings.

Read them very carefully. If you don’t understand why a warning is being produced, that’s a good question for StackOverflow because it is a specific question about actual code. Be sure to post the exact text of the warning, the exact code that produces it, and the exact version of the compiler you’re using.

If your program still has a bug, obtain a rubber duck. Or if a rubber duck is unavailable, get another computer science undergraduate, it’s much the same. Explain to the duck using simple words why each line of each method in your program is obviously correct. At some point you will be unable to do so, either because you don’t understand the method you wrote, or because it’s wrong, or both. Concentrate your efforts on that method; that’s probably where the bug is. Seriously, rubber duck debugging works.[1. And as legendary programmer Raymond Chen points out in a comment to this entry, if you can't explain to the duck why you're executing a particular statement, maybe that's because you started programming before you had a plan of attack.]

Once your program compiles cleanly and the duck doesn’t raise any major objections, if there’s still a bug then see if you can break your code up into smaller methods, each of which does exactly one logical operation. A common error amongst all programmers, not just beginners, is to make methods that try to do multiple things and do them poorly. Smaller methods are easier to understand and therefore easier for both you and the duck to see the bugs.

While you’re refactoring your methods into smaller methods, take a minute to write a technical specification for each method. Even if it is just a sentence or two, having a specification helps. The technical specification describes what the method does, what legal inputs are, what expected outputs are, what error cases are, and so on. Often by writing a specification you’ll realize that you forgot to handle a particular case in a method, and that’s the bug.

If you’ve still got a bug then first double check that your specifications contain all the preconditions and postconditions of every method. A precondition is a thing that has to be true before a method body can work correctly. A postcondition is a thing that has to be true when a method has completed its work. For example, a precondition might be “this argument is a valid non-null pointer” or “the linked list passed in has at least two nodes”, or “this argument is a positive integer”, or whatever. A postcondition might be “the linked list has exactly one fewer item in it than it had on entry”, or “a certain portion of the array is now sorted”, or whatever. A method that has a precondition violated indicates a bug in the caller. A method that has a postcondition violated even when all its preconditions are met indicates a bug in the method. Often by stating your preconditions and postconditions, again, you’ll notice a case that you forgot in the method.

If you’ve still got a bug then learn how to write assertions that verify your preconditions and postconditions. An assertion is like a comment that tells you when a condition is violated; a violated condition is almost always a bug. In C# you can say using System.Diagnostics; at the top of your program and then Debug.Assert(value != null); or whatever. Every language has a mechanism for assertions; get someone to teach you how to use them in your language. Put the precondition assertions at the top of the method body and the postconditions before the method returns. (Note that this is easiest to do if every method has a single point of return.) Now when you run your program, if an assertion fires you will be alerted to the nature of the problem, and it won’t be so hard to debug.

Now write test cases for each method that verify that it is behaving correctly. Test each part independently until you have confidence in it. Test a lot of simple cases; if your method sorts lists, try the empty list, a list with one item, two items, three items that are all the same, three items that are in backwards order, and a few long lists. Odds are good that your bug will show up in a simple case, which makes it easier to analyze.

Finally, if your program still has a bug, write down on a piece of paper the exact action you expect the program to take on every line of the program for the broken case. Your program is only twenty lines long. You should be able to write down everything that it does. Now step through the code using a debugger, examining every variable at every step of the way, and line for line verify what the program does against your list. If it does anything that’s not on your list then either your list has a mistake, in which case you didn’t understand what the program does, or your program has a mistake, in which case you coded it wrong. Fix the thing that is wrong. If you don’t know how to fix it, at least now you have a specific technical question you can ask on StackOverflow! Either way, iterate on this process until the description of the proper execution of the program and the actual execution of the program match.

While you are running the code in the debugger I encourage you to listen to small doubts. Most programmers have a natural bias to believe their program works as expected, but you are debugging it because that assumption is wrong! Very often I’ve been debugging a problem and seen out of the corner of my eye the little highlight show up in Visual Studio that means “a memory location was just modified”, and I know that memory location has nothing to do with my problem. So then why was it modified? Don’t ignore those nagging doubts; study the odd behaviour until you understand why it is either correct or incorrect.

If this sounds like a lot of work, that’s because it is. If you can’t do these techniques on twenty line programs that you wrote yourself you are unlikely to be able to use them on two million line programs written by someone else, but that’s the problem that developers in industry have to solve every day. Start practicing!

And the next time you write an assignment, write the specification, test cases, preconditions, postconditions and assertions for a method before you write the body of the method! You are much less likely to have a bug, and if you do have a bug, you are much more likely to be able to find it quickly.

This methodology will not find every bug in every program, but it is highly effective for the sort of short programs that beginner programmers are assigned as homework. These techniques then scale up to finding bugs in non-trivial programs.

About these ads

93 thoughts on “How to debug small programs

  1. The average guy posting this kind of questions on SO is probably in CS101 taking it for an “easy minor”, doesn’t actually understand any of the code and is just pasting together bits from their materials.

      • While what Lloigor has said may be true, I would like to thank you for the write up. I’m only in CS202 but I’m in CS for the long haul and really appreciate the tips.

        • You’re very welcome!

          I would take this opportunity to inform you, if no one has already, that designing, implementing, testing and debugging code is not the purview of computer science. As Dijkstra famously pointed out, just as telescope design and construction is not the job of astronomers, program design and construction is not the job of computer scientists.

          If you’re studying CS to learn how to program, you might be in the wrong course of study.

          • When I went to university, this was very true. I was there to learn CS rather than programming though, so I was happy.

            When I went into the real world, I found a learning curve that was about as steep as my Masters thesis was, which also made me happy.

            However, I wonder if that has changed a bit. At least around here. Although the name of the major may not have changed, I see new grads with more work-appropriate skills more often. They get taught UML and stuff.

          • On the other hand, if you want to learn how to use a telescope but no one is offering degrees in Telescope Management, pursuing Astronomy isn’t the _worst_ course of action around.

          • My teachers had certainly stressed that my diploma was going to be more immediate-job-skill oriented than a CS degree, but I only had a vague notion of what the CS guys were up to.
            Pair programming with a CS guy has been the best experience of my career.

    • CS as an easy minor? My mind boggles.

      I have however met a lot of people who studied programming for the money rather than any innate interest. Tends not to work out well.

    • “The average guy posting this kind of questions on SO is probably in CS101″
      or is one of my co-workers. Seriously, there are a lot of ‘cut and paste’, ‘learn one trick and repeat’ programmers out here.

  2. http://en.wikipedia.org/wiki/5_Whys

    Ask yourself why you might be seeing the behaviour you’re seeing. For example if it’s an exception, ask yourself what code threw the exception, then when you’ve figured that out ask why it threw the exception. Repeat until done. If you get stuck, be prepared to reexamine your conclusions to the earlier questions.

  3. As a mentor of a programming course for beginners at university I really appreciate this post and hope a lot of people read it before trying to get other people to do the dirty work for them.

    My observations:
    Rubber duck is a very good technique for short programs (up to about a hundred lines or as long as you can explain what EVERYTHING does without skipping parts).

    Second, not as much of a debugging tip, but a design tips for beginners. Say you want something done; the best possible situation is that there already is a function that does exactly that. If not then imagine that there is one and use it. After that you implement it and repeat the process.

    Lastly, do learn how to use debugging tools for your language. There is no quick fix for finding out that you simply implemented the algorithm wrongly.

    • Rubber duck is also a good strategy for asking questions. I’ve found that the act of even *trying* to post to stackoverflow pretty much forces me to listen to small doubts, because if I don’t do so, I know respondents will be too “distracted” by things which are “obviously*” not the real problem.

      *in this context, “obviously” means “sometimes.”

      • Yep. The ratio of questions I’ve started to questions I’ve actually finished and posted on StackOverflow is about 3:1. So often, my attempts to anticipate the questions that other people are going to ask me lead me directly to the solution to the problem I’m facing.

    • I agree with points 2 and 3, but I find that rubber ducking works not only on small programs, but massive ones too. The trick there is to have a mind map of the portion of the code you are working on, that way you are forced to examine just that portion, hence taking a large application and making it small, encapsulating it essentially. I rubber duck all the time, and it solves most issues. When it doesn’t, debug the hell out of it, watching all variables pertinent to the result.

  4. For StackOverflow, I would suggest moving to the rubber duck stage once you get past the compiler warnings. Because *everybody else on StackOverflow is a rubber duck* with respect to your program. (If you don’t know what the value of the variable “x” is supposed to be at line 10, how do you expect anybody else to know?)

    Beginners often have trouble debugging because they haven’t yet learned how to *code*. The code doesn’t have a plan. It’s just a bunch of syntactically legal statements. The rubber duck forces the beginner to actually develop and then describe the plan.

    Preconditions and test cases are great, but they are useless if you don’t have a plan.

  5. In college I used rubber duck debugging on an 8500 line project as a last resort. My partner and I made some educated guesses as to where the bug was first of course and started with those files. For the code I wrote he read it to me, for the code he wrote I read it to him. Until indeed I hit a line where I said “wait, what does this do?” And that was the bug. 2 hours spent.

    It sounds slow, but compared to shooting in the dark for days or weeks on end, 2 hours is cheap. We’d already waisted 2 days looking for the bug using other techniques.

    Since then I’ve used it numerous times, even on fairly large projects, particularly once you know the bug is in some hundreds of lines of code.

    • I absolutely agree. I’ve used it often enough on largish modules of a codebase with hundreds of kloc.

      My version of it is to wander into someone’s office, interrupt them, and start explaining my problem. A few minutes in, I answer the problem myself, thank them and leave.

      They usually turn around to look at me out of politeness, but don’t speak a word.

      I’m sure they regard it as part of my personal charm.

      • I do similar with one of my testers. He listens intently never understanding a word, but somehow believes that he perhaps should. It’s all smiles when I thank him and leave.

  6. Great post! I do, however, think a bit more detailed information could be added about using a debugger, breakpoints, (auto) watches etc. and for environments where you don’t have a good debugger available, as a last resort, things like “var_dump($foo)” or “echo $bar” or “logger.Log($myar)” e.g. “log/dump debugging” and other means of inspecting variables. Other than that it’s a great post.

  7. Additional tips for when you’re still stuck:

    Binary search for the problem. Remove a chunk of code and verify that the remaining part behaves as expected. If it does, add some of the removed code back. If it doesn’t remove another chunk of code. Repeat until you find the chunk that causes the problem. (Especially good if your code is longer than 20 lines and loosely coupled. Before RAII was common, I used to use this to track down resource leaks in record time.)

    Make intermittent problems happen consistently. If the problem happens sometimes but not always, then you need to find (and eliminate) the causes of randomness (at least for the duration of debugging). Uninitialized memory (initialize everything), events that can happen in a different order (make them scriptable or create a way to record and play back inputs), race conditions (check thread synchronization) and–of course–random number generators (make a way to seed them consistently from run to run).

    • Hear hear.

      I use the binary chop technique when all else fails, for those extremely unexpected bugs like memory corruption or when debugging is for some reason impossible.

    • +1 for binary search. I tend to apply this not by cutting out code, but by setting breakpoints and checking my assumptions on what the variable values are at that point.

    • The advice to “Make intermittent problems happen consistently” cannot be stressed enough. An intermittently failing test is a serious problem and a strong indicator that reassessment is needed. It generally implies the existence of dependencies that are not taken into account by our design.

      In general, programming curricula fail to sufficiently emphasize the importance of testing. Writing tests must not to be thought of as a chore, or some “extra work”, it is fundamental.

  8. For debugging really small programs (less than 10 lines and no deeply nested loops), I usually use do the simple thing: run the program under the debugger and check that every variable has the value I expect it to have at that place. (Of course, only the variables assigned/accessed in the every current line are interesting.) If at the end every value is correct, the result is correct as well; otherwise, the first place where the value is not equal to expected one is where the mistake is.

    For the longer code, splitting it into smaller parts helps to make finding the problem a kind of binary search. Of course, if the program is well-structured (at least split into meaningful functions), such a search is much easier, since one can estimate the return value of a function just by its name.

    • I agree. For something 20-lines long, it’s as simple as: 1. Articulating (on paper, to a colleague, or to yourself) what the thing is supposed to do, and 2. Stepping through it in a debugger and seeing if it really does that.
      This is all well and good now though, since we’ve got visual debuggers. 20-something years ago, the source code and the errors/warnings were the only things people had, so all other, non-visual techniques like rubber duck debugging were essential.
      Also, if it’s just 20 lines long, what’s there to split into smaller parts? Even if half of those 20 lines are not the using directives and various mandatory declarations?

      • What were you programming 20 years ago? Most languages I were programming had great debuggers. Even assembler had debuggers with breakpoints and memory content. For example Devpac 3 for the Atari ST/E from 1992.

        • Twenty years ago, I was using the first 16-bit versions of VC++. A year or two earlier, it was C with CodeView. Not very many years before that, it was C on 8-bit CP/M and/or embedded systems. I remember having the print out of a MAP file in one hand, and an in-circuit emulator (that only showed machine-code in it’s output) in the other. When you found the bug, it meant burning a new EPROM and going from there.

          The tools are *a lot* better today.

          • For CS101, you don’t need a debugger, you just add print statements.

            I do have to say that I’ve always been appalled at how rarely simple debugging skills are taught. Somehow the students are expected to pick it up by osmosis.

            I like the rubber-duck idea. When I wrote a textbook chapter on debugging (for HS’ers) many moons ago, I didn’t think about the “explain it in simple language” first.

  9. I just want to point out that a Teddy Bear is superior to a rubber duck. Why? Because Alan Turing had one named Porgy. He used to explain the problems he was working on to Porgy and Porgy helped him.

  10. Another technique I use, particularly for methods with tricky algorithms, is to hand-execute the code on a piece of paper. This establishes whether its my idea of the algorithm that is at fault, or my translation of the algorithm into code. The debugger can only focus on the latter, a piece of paper and a pen focusses on the former.

      • While you suggest it last, I generally suggest it first. The sort of person who asks the Internet to help debug their 20-line program would probably take days to fully comprehend concepts like compiler warnings, methods, preconditions, assertions, and technical specifications.

        Executing the program by hand, however, is something easily understood by even a 10-year-old.

        Of course that only works if you understand your program in the first place. If you didn’t write it (perhaps you copied it from somewhere), you may not understand it, in which case you have to start with the rubber duck.

        I should also add that an important step in rubber duck debugging is to delete the parts you don’t understand. If you can’t figure out what some code does, it probably shouldn’t be in your program!

        Only once you have a program you completely understand can you single-step through it to figure out where your assumptions about what it’s supposed to do are wrong.

        • “If you can’t figure out what some code does, it probably shouldn’t be in your program!”

          Indeed. If I’m looking at somebody else’s program, and I don’t understand some fragment of code, my first assumption is that it is wrong.

          Even if it is just some very complicated but correct code written by a genius, it is still wrong, from a maintenance perspective. For maintainability, not only the original author must be able to understand it, but other people as well.

  11. You left out my favorite debugging trick, using print/console statements to show the value of variables.

    I know it’s ugly and not “correct”, but it works.

    • I guess the idea is that the debugger can do exactly that for you, except more cleanly.

      However, I have done this often myself. Either the breakpoint is only interesting once out of the thousands of times the line is hit, and conditions on the breakpoint aren’t good enough for some reason; or timing is important to the bug, so I have to let it run at near-normal speed; or I don’t have a debugger.

      Actually, it’s kinda scary for how much of my career I have lacked a debugger.

      • It’s probably just me, but so far I still have no idea how to debug bash scripts or makefiles (oh the horror) in any way other than using printf debugging.

        It may not be the most efficient way to approach a problem, but it works in any language (everything has some kind of output), doesn’t need any tools (so works everywhere) and you actually can get surprisingly far with it.

        Doesn’t mean I’d use it instead of a debugger when working on C# code, but I find it’s still a good tool to have in your toolbox.

        • Next time you need to debug a bash script, try putting:
          set -x
          before the part of the script which isn’t working.

          – Les

    • one could argue this is a poor man’s logging framework rather than a poor man’s debugger. Which of course suggests that read the logs is a very crucial step for any program that produces some sort of log

    • I’m mostly from the Microsoft (DOS/Windows) background and as such, have had a few, shall we say, heated arguments with the UNIX people who just love, love, LOVE log files. Even in a multi-threaded environment, where writing a line in a log file actually changes the program’s behaviour, they would not change.

  12. Sometimes I like to focus on the bug, especially for very short programs. I try to write the shortest possible program that exhibits the bug I am working on.

    When the code gets short enough, often the bug becomes obvious.

    Bonus: if the bug isn’t mine, I got a repro for the person I report the bug to.

    I will also opine that it is in debugging, not coding, where the best computer scientists show their stuff. I remember watching one of my professors spend several hours debugging. (The bug was right on the interface between my code and the code he supplied to get us started.) It was one of the most educational days of my four years at the university.

    • Every program has at least one bug and can be shortened by at least one instruction — from which, by induction, one can deduce that every program can be reduced to one instruction which doesn’t work.

      Not sure who first said that.

  13. … if a rubber duck is unavailable, get another computer science undergraduate, it’s much the same.

    I have to disagree with this. One of the guys in our company used to have a couple of CS undergrads on his desk. We then discovered several advantages of rubber ducks over students:
    1. rubber ducks don’t require any food.
    2. rubber ducks don’t make weird unexpected noises.
    3. when you hit rubber duck with a mallet it doesn’t call the police.

    I used to talk regularly with a rubber duck through my whole software development career. Doctors keep telling that I should stop following its advice. They just don’t understand… Only duck understands me.

  14. 1) Here at work we talk about the ‘yes man': the colleague who just has to nod and say ‘yes’ while you explain the problem. 9 times out of 10 you’ve found the problem before he’s even understood what you’re talking about. Other times, they will ask ‘stupid’ questions, which will immediately open your eyes. And sometimes they will just glance at the screen and say: “Line 93, you inverted the condition”.

    2) A handy and not-very-well-known function in VS is the “When Hit” option on Breakpoints (right-click on the breakpoint ‘circle’): this allows you to insert pseudo Debug.WriteLines into your code without leaving breadcrumbs everywhere which you need to remember to clean up afterwards.

    3) Another element of debugging not invoked here is when you have new bugs: it’s useful to think about what has changed in the code, and when. (aka Use Source Control Or Perish)

    • Use Source Control Or Perish

      The blame pointer is the idol which we programmers all worship.

      Corporate and soulless version control systems call it annotate, but we all know what it really is.

  15. Actually we should have to consider of naive or new users. The way Stack-overflow old-users/moderator behaves with naive or new users is very discouraging and ridiculous.

  16. Great post! Most people ignore this. Before I post my problem in stackoverflow I spend time trying to post a very specific problem, for which I try to write a separate generic program that has the problem. And in doing so it suddenly gives me new insights that solves my problems !

    This is a very basic and most essential step in problem solving. Even after all this there will be problems we will be unable to solve and that is what stackoverflow is for ….

  17. quack quak,

    spot the bug?

    Ducks will eat bugs, quickest way to get lean sometimes is Occam’s Razor…

    nice post Eric!

  18. I learnt this trick more years ago than I care to remember. I knew the “rubber duck” as the “cardboard programmer” Just used to draw a face on the back of a punch-card and explain the code. 9 times out of 10 would spot the problem using this manner. Have to say at the time I was maintaining some very old (archeological) IBM Assembler… Great post. Hope people read this and apply the techniques.

  19. Sorry, sir – I disagree, I think the lack of specific “how you use a debugger-tool” is what makes this post worth reading.

    Using a debugger-tool isn’t that difficult and you can use it (as I have many times) but without actually understanding your code much better.

    The ideas in this post instead focus on learning from your mistakes and how to avoid them in the future.

    These ideas are also somewhat scalable. 20 lines of badly written code will go fast to debugg – 100 lines not so fast anymore. A debugger-tool should more or less be your last option for a specific case, and when you get to that there are several articles about how to use your debugger best.

  20. This is a great article. Sadly, the same people who are too lazy to debug their 20-line program will also be too lazy to read this article and will continue to post, “Here’s my code, it’s broken, fix it for me.”

    • Well, we could use Hanlon’s Razor and assume charitably that until proven otherwise those people are ignorant rather than lazy.

      When I did my undergraduate CS work I very frequently biked in first thing in the morning and found classmates who were asleep in the lab because they’d been up all night trying to debug a 20 line program. These people were not lazy, they had just never been taught any methodology for debugging other than “make random changes until it works”.

      • When I was training as an electronics engineer back in the 1970’s we had a module in our course on fault finding. It taught us how to find faults on designs and code and even programs (assembler of course :-) It was examinable. It was almost entirely generic and I’ve applied those techniques to every problem in a design in my career ever since (90% of which has been in software/IT).

        I was shocked and amazed to discover that CS grads didn’t get such training. And even more shocking is that they still don’t. I’m still not sure why. The material has been around for years, it would not be hard to include in courses.

  21. Not *exactly* on topic, but close enough, I think, to be useful. My short essay “Programming a Dishwasher” at http://lrs5.net/FTPData/ tells of how I got the overall concept of programming across to someone who hadn’t really figured it out yet. And I did it without involving computers!

    P.S. to Eric — as a former Waterloonie yourself, you might also be interested in my Red Room essay on the same FTP page.

    • My kids enjoy learning how to program, even as early as 3 years of age. The fun game for them is programming me to make chocolate milk. Of course they don’t write down the steps, I just do things as they tell me.

      They think it’s hilarious when they tell me to take the milk out of the refrigerator without telling me to first open the door, and I say “I don’t see any milk!”. Or when they forget to tell me to take the lid off the jug before instructing me to pour the milk, and I tip the jug with the lid still on. For added fun, move and talk like a robot!

      And as they get better at “programming”, I can increase the number of steps, and get them to learn concepts like left vs. right and even clockwise vs. counterclockwise (one direction gets the lid off, the other puts it back on).

  22. Another possible approach (for smaller code) is to rewrite it using different logic (different data structure, flow..) and compare the results and find the bug in the original code.

    Or if you have attempted an optimization in the original, try writing the un-optimized version.

  23. I’ve always been a big fan of Steve Macguire’s advice in _Writing Solid Code_: Always step through new code. Always.

    It’s excellent for quick and dirty programs, and it’s an excellent complement to test-driven development.

    I set breakpoints at the beginning of every basic block as I write new code. Then, when I run the tests, I remove each breakpoint after stepping through that basic block and making sure everything behaves exactly as I’d expect. If I have any breakpoints left, then my test coverage was incomplete, and I add more tests until all the breakpoints are removed.

    Stepping through in the debugger also makes it possible to quickly simulate failures that might otherwise be hard to induce in a test. For example, if the new code calls a factory to get a new Foo, you can trounce the pointer in the debugger while you’re stepping through the code to ensure that you cover that code that handles a failure to create a new Foo.

  24. In my experience rubber duck concept works very well in large programs/methods as well. I have been involved in same scenarios multiple times and i have learnt that if you show your code to someone else and that person if ask’s you questions like “what are you trying to achieve by this method” or “what is the purpose of these set of lines” which are intriguing in nature, you sometimes tend to find the problem while explaining else they may be able to find possible issues for you.

  25. Great article – especially important to point out that using the debugger should be a /last/ resort, not a first resort when resolving bugs.

    Another good approach can be to triangulate problems (may be more relevant in > 20 lines of code). If there are multiple unexpected input/output combinations, perhaps you can reason why those particular cases behave the way they do to help narrow down the problem.

    In much larger programs this is especially useful as it maybe gets you to the right area for more detailed debugging.

  26. My tip is F10. Step through the code, line by line, and check that what happens is what you expect to happen.

    The first few times it helps if someone holds their hand, to push them through when they get stuck and ask questions that hint at the right answer.

    Of course someone who has no specific expectations (because they don’t even have a very clear idea of how their code is supposed to do that thing they’re trying to achieve) will not be helped by this.

  27. I would like to add a way of debugging that has helped me a lot. I noticed that I find and solve bugs much faster in this way than in the others. It’s based on the scientific method, although I realized that years after I was doing it.

    What I do when I have a bug is to formulate a hypothesis of what could go wrong. I then use a unit test or the debugger to validate the hypothesis. Once I validate it, I change the code and validate that it works (ideally with tests).

    Some example of hypothesis:
    * “This problem is most likely to come from class X, method doSomething(), if it returns the wrong value.” -> use the debugger or a unit test to see if it actually returns the wrong value, or temporarily change its return value to the correct one (eg. return “a correct string”) and see if the bug still reproduces
    * “This bug probably happens because the call to service X comes before the call to service Y” -> temporarily remove the call to service X and see if the bug still reproduces
    * “An exception is probably thrown in a class and swallowed in class Z” -> remove the exception management code and check that the exception is actually thrown

    As you can see, once you formulate the hypothesis it’s relatively easy to identify the experiment.

    It’s hard to explain how to formulate the hypothesis, because I’m doing that automatically, but I’ll try. First, I try to visualize the code path for the bug. Second, I mentally ignore everything that works right, based on other features that use the same code. Third, I take what remains and think of the most probable error.

    I hope this helps.

  28. OK, I know that being hypocritical doesn’t necessarily negate the value of the argument.

    Having that out of the way, this post should be read in light of Mr. Lippert’s high reputation, resulting from – well – upvotes he got from others on SO.

    Yet Mr. Lipper’s voting history is at this moment as follows: ~1k downvotes, ~1 upvote. Seriously. The heck?

    • I’m not following your train of thought here. First, why ought this post to be read in the light of any number of fake Internet points? This post gives good technical advice to beginners; the quality and usefulness of that advice is indepdent from the number of fake Internet points anyone has.

      Second, what’s the alleged hypocrisy?

      Third, you’re right, that is weird. The one upvote was an accident, and by the time I realized it, the vote was locked in. I was trying to reverse a downvote on a post that had been edited to remove the mistake.

      You might be under the misapprehension that the purpose of voting on StackOverflow is to assign fake Internet points to the worthy. That is not a goal I care about in the least. The proper function of voting is to identify poor quality questions and answers so that they can be deleted before they harm others.

  29. One thing i didn’t see is *data tracing*. I can’t tell you how many bugs I’ve found by reading code not in the order it’s written, but in the order that a variable or set of variables (the ones that are turning up incorrect) are being modified.

    I’ve found that if I can’t trace data without actually running the program, then I’ve obfuscated the code too much to be reliably read, and I need to clarify it. That usually resolves the problem. If I *can* trace the data, it’s a very simple process to resolve when I find the modification that makes it erroneous.

    As far as small vs. large programs, if it’s being modularized properly, it should be very simple to imagine that a very large program is actually just a very large number of small programs playing nicely with each other.

  30. Pingback: Embedded Link Roundup | UpEndian

  31. Hey Eric – A great article….!!!
    Learned many new things from it and comments under post. I would like to thank all the programmers on this post thread for sharing your ideas and ways of debugging. That’s really helpful and good to improve your knowledge.

    Happy Coding…:)

  32. Great advice. With techniques like this I managed to have a Q/A ratio of 2/450 on SO – the two questions not being bug-related. I agree with others who say that this is not only applicable to debugging of 20-liners. It can also be used in programs of several million LOC, when you have already tracked the bug down to be “somewhere in these 1000 lines”.

  33. Pingback: How to Debug Small Programs - Edge Cases

  34. Over the course of the year, by letting the staffing company keep their commission, you could lose out
    on $50,000. Aerospace manufacturers make up another
    market with strong potential for 3-D printing technology because of its ability to convert
    designs to 3-D models almost instantly. Monstercourses is having fully qualified and
    industry experts who can teach quality online training to
    the students,.

  35. Pingback: How to create/debug small, OWL based ontology | deprecated blog

  36. Pingback: 4. 良い質問をするには? | Stack Overflow Help Center 日本語版

  37. Pretty element of content. I just stumbled upon your blog and in accession capital to assert
    that I acquire actually enjoyed account your blog posts.
    Anyway I’ll be subscribing to your augment and even I achievement
    you get admission to persistently fast.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s