Slashdot Mirror


New & Revolutionary Debugging Techniques?

An anonymous reader writes "It seems that people are still using print statements to debug programs (Brian Kernighan does!). Besides the ol' traditional debugger, do you know any new debugger that has a revolutionary way to help us inspect the data? (don't answer it with ddd, or any other debugger that got fancy data display), what I mean is a new revolutionary way. I have only found one answer. It seems that Relative Debugging is quite neat and cool."

9 of 351 comments (clear)

  1. Avoid debugging by heironymouscoward · · Score: 5, Insightful

    You get what's called 'glassnose syndrome' too easily.

    Instead concentrate on building software in many small incremental steps so that problems are caught quickly, and on separation of design so that dependencies are rare.

    If you can't find a problem, leave it and do something else.

    Otherwise, print statements, yes, that's about the right level to debug at.

    --
    Ceci n'est pas une signature
    1. Re:Avoid debugging by mattgreen · · Score: 4, Insightful

      Ah, nothing like claiming that your way of approaching something is the only way. A debugger is just a tool. Like any other tool it can be bad if it is misused, and it isn't appropriate for every situation. I find a debugger invaluable for jumping into someone else's code and seeing exactly what is happening step-by-step. Debuggers can be great if you suspect buffer overflows and don't have access to more sophisticated tools that would detect it for you. Just yesterday I used a debugger to modify values in real-time to test code coverage.

      Inserting printf statements into the code is probably not logging - usually if you are debugging they are destined for removal anyway. I use a logging system that shows the asynchronous, high-level overview of events being dispatched and then can use the debugger to zero in on the problem very quickly without recompiliation. In addition if a test machine screws up I can remotely debug it.

      If you want to throw out debugging because Linus isn't a fan of it, be my guest. But I'm not a fan of wasting time, and injecting print statements into the code plus recompiling is a waste of time and ultimately accomplishes close to the same thing as debugging. Any decent IDE will let you slap a breakpoint down and execute to that point quickly. But I assume someone will come along and tell me that IDEs are for the weak as well.

  2. Hey, nice ad! by EnglishTim · · Score: 4, Insightful

    I can't escape the suspicion that the anonymous poster is actually in some way connected to Guardsoft, but let's leave that for now...

    I think it's a good idea, but I do wonder how many situations you'll be in where you already have an exisiting program that does everything you want to test against.

    Having said, that, I can see how this would help with regression testing - making sure that you've not introduced any new bugs when fixing old ones. But I wonder how much it gives you above a general testing framework anyway...

    1. Re:Hey, nice ad! by fishdan · · Score: 5, Insightful
      I agree with you. I would have rather seen it posted without a reference to guardsoft and have someone mention it. I'm all for advertising on /. -- just not in the form of news.

      The fundamental issue here is that people are ALWAYS looking for a way to avoid having to write unit tests. I'm happy with a combination of Intellij and print statements. So far I've never had a situation where I though "the debugger isn't giving me enough information."

      I think that one of the reasons I'm happy with the debugging options available to me, is that I write my code so that it can be easily followed in the debugger. That means splitting my declarations and assignments, and other such things that make my code a bit more verbose, but eminently more readable. Lord knows as a child, I loved those complicated boolean switches, and cramming as much line into one line of code as possible. Now that my code is maintained by more people than me, I'm tired of people having ot ask me "what does this do." I used to get angry at them, but now I get angry at myself when that happens. We don't just write code for the users, we write it for our peers. Write code that your sibling developers will be able to follow in a debugger. I know some code is hard to follow, even with a debugger, so I write all my conditions as clearly as possible, name my methods and variables as clearly as I can and refactor reusable code into well named "submethods", so that we can solve "modules".

      This is because I want my code to last beyond my employment. Therefore it has to be maintainable by someone other than me. The real test of your code is: can someone ELSE debug it, using whatever the heck tools they want. A fancy debugger is a fine thing, but someday someone is going to have to debug your code with inadequate tools. My rule of them is "Code as if your life depended on someone else being able to fix it"

      --
      Nothing great was ever achieved without enthusiasm
  3. Old methods best. by hegemon17 · · Score: 4, Insightful

    "Relative debugging" seems to be what people have always been doing. Dump some state and comapre it to an expected state. Most frameworks for regression tests do something like that.

    The best debugging method is to have a fast build environment so that you can add one printf, rebuild, reproduce the bug, move the printf to an even better place, rebuild and reproduce, etc. The more you rely on your tools to do the work for you, the less you understand the code and the less you understand the code, the more bugs you will make in the future.

    There are no shortcuts to good code.

  4. Re:Print statements work fine for me, too by Gorobei · · Score: 5, Insightful

    Print statements are a great tool, especially on large pieces of software maintained/enhanced by many people. Once you've debugged your problem, you just #ifdef out the prints, and check the code back into version control.

    When the next poor programmer comes along, trying to fix/find a bug in that code, he a) can #ifdef the prints back on and quickly get debugging output about the important events taking place in his run, and b) read the code and see where the hairy bits are, because they tend to be the sections most heavily littered with debugging print calls.

    Fancy debugger IDEs just don't support this preservation of institutional knowledge.

  5. Re:Data logging by Tim+Browse · · Score: 4, Insightful

    Of course, as many people who debug multi-threaded programs have found, using print routines to output logs can make the bug 'go away', because quite often CRT functions like printf() etc are mutex'd, which serialises code execution, and thus alters the timing, and voila, race condition begone!

    I know it's happened to me :-S

  6. don't debug by mkcmkc · · Score: 5, Insightful
    • The best programmer I've met once told me that once you've dropped into the debugger, you've lost, which over time I've found to be quite true. The best debugging practice is to learn how not to use a debugger. (e.g., Are you using threads when they're not absolutely required? Say hello to debugging hell...)
    • When you must debug, print statements cover 97% of the cases perfectly. They allow you to formulate a hypothesis and test it experimentally as efficiently as possible.
    • Differential debugging is a nifty idea, but most of the time it'd be better to just use it with your print statements as above (e.g., print to logs and then diff them). For the one time per year (or five or ten years?) that having a true differential debugger might pay off, it's probably a loss anyway because of the cost and learning curve of the tool. (I thought about adding this to SUBTERFUGUE, but realized that no one would likely ever productively use this feature.)
    • If you need another reason to avoid this tool in particular, these guys have a (software) patent on it. Blech!
    --Mike
    --
    "Not an actor, but he plays one on TV."
  7. So I need two running programs to debug relatively by Ricdude · · Score: 4, Insightful
    If I had a working program in the first place (to compare my buggy program with), I wouldn't need the debugger.

    Seriously, though. I've worked as a programmer for the last 15 years. Mostly, I've been fixing other people's bugs. Here's what I like to see in code that I need to fix (and generally don't see):

    1) Consistency in formatting, style, variable names, design - I don't care what style you use as long as it's consistent. I prefer my own form of Hungarian Notation, where a variable's prefix indicates its scope (global, static, etc), as well as the type. If any of that information changes, I should darn well follow through to make sure I've fixed everything that depends on them. Bring on strong type checking!

    2) No spaghetti code. Give me this:

    if ( something_bad ) {
    return failure;
    }
    good_stuff();
    return good;
    instead of this:
    if ( ! something_bad ) {
    good_stuff();
    return good;
    }
    return failure;
    It doesn't look like it matters much yet, but try adding eight more error checks to both, and see which you can track better. The "early bailout on error" model clearly surpasses the "endless nesting" model.

    3) Use of descriptive variable and procedure names. Source code is not meant to be understood by the computer. This is why we have compilers, and interpreters. Source code is meant to be understood by humans. Write your code for humans, and you'll be surprised at how much faster you can grind through code. You'll only write the code once, but when you have to debug it, you'll spend eternity sifting through line after line, wondering what the hell you meant by that overused "temp" variable (temporary value? temperature? celsius? kelvin?). If you had only taken the time to spell out, "surface_temperature_C", you'd know for sure. Vowels are good for you.

    4) Comment! Not every line. Not an impossible to maintain function header comment with dates and initials of everyone who's edited it. Don't fall for nor rely on that "self-documenting" code nonsense. Just one comment line every three to ten code lines. That's all. Give me an overview of what's supposed to happen in each logical block of code. Tell me what if conditions are checking for. A good rule of thumb is to sketch out your functions in comments first, then fill in the blanks.

    That's all I can come up with off the top of my head, but there are certainly more...

    NOTE: for the pedants who think they noticed an apparent conflict between my hungarian notation style and the "surface_temperature_C" variable: since there is no scope or type prefix on the variable, it's a local variable, and I can change it at will, knowing that it will not affect any code outside the function at hand. If it had been "m_fSurfaceTemperature_C", then I'd know it could have repercussions affecting the state of the current object. If it were "g_fSurfaceTemperature_F", then I'd know I could hose my whole program with an invalid value. And should have converted from Celsius to Fahrenheit before doing so...

    --
    How's my programming? Call 1-800-DEV-NULL