tags:

views:

2352

answers:

22

I've been a software developer for over twenty years, programming in C, Perl, SQL, Java, PHP, JavaScript, and recently Python. I've never had a problem I could not debug using some careful thought, and well-placed debugging print statements.

I respect that many people say that my techniques are primitive, and using a real debugger in an IDE is much better. Yet from my observation, IDE users don't appear to debug faster or more successfully than I can, using my stone knives and bear skins. I'm sincerely open to learning the right tools, I've just never been shown a compelling advantage to using visual debuggers.

Moreover, I have never read a tutorial or book that showed how to debug effectively using an IDE, beyond the basics of how to set breakpoints and display the contents of variables.

What am I missing? What makes IDE debugging tools so much more effective than thoughtful use of diagnostic print statements?

Can you suggest resources (tutorials, books, screencasts) that show the finer techniques of IDE debugging?


Sweet answers! Thanks much to everyone for taking the time. Very illuminating. I voted up many, and voted none down.

Some notable points:

  • Debuggers can help me do ad hoc inspection or alteration of variables, code, or any other aspect of the runtime environment, whereas manual debugging requires me to stop, edit, and re-execute the application (possibly requiring recompilation).
  • Debuggers can attach to a running process or use a crash dump, whereas with manual debugging, "steps to reproduce" a defect are necessary.
  • Debuggers can display complex data structures, multi-threaded environments, or full runtime stacks easily and in a more readable manner.
  • Debuggers offer many ways to reduce the time and repetitive work to do almost any debugging tasks.
  • Visual debuggers and console debuggers are both useful, and have many features in common.
  • A visual debugger integrated into an IDE also gives you convenient access to smart editing and all the other features of the IDE, in a single integrated development environment (hence the name).
+23  A: 
  • An IDE debugger lets you change the values of variables at run-time.

  • An IDE debugger lets you see the value of variables you didn't know you wanted to see when execution began.

  • An IDE debugger lets you see the call stack and examine the state of the function passed weird values. (think this function is called from hundreds of places, you don't know where these weird values are coming from)

  • An IDE debugger lets you conditionally break execution at any point in code, based on a condition, not a line number.

  • An IDE debugger will let you examine the state of the program in the case of an unhandled exception instead of just crapping out.

recursive
@Joe, in the context of Bill's question, I think they _are_ equivalent. Bill's talking about printf debugging. Whether the debugger is integrated with the editor and the compiler is immaterial at that point.
Rob Kennedy
the thing is that gdb, which is not an IDE debugger, has all these features
DrJokepu
The question was about IDE debuggers vs print style debugging, so I'll leave it as it is.
recursive
Yes, those are very valid advantages of debuggers. I understand these features are available in console debuggers too, but they are certainly good answers to my question.
Bill Karwin
+1  A: 

I haven't been developing for nearly 20 years, but I find that using a IDE / debugger I can :

  • see all kinds of things I might not have thought to have included in a print statement
  • step through code to see if it matches the path I thought it would take
  • set variables to certain values to make code take certain branches
Kevin Davis
Good points! Certainly these can reduce repetition of "edit, recompile, run."
Bill Karwin
+47  A: 

Some examples of some abilities that an IDE debugger will give you over trace messages in code:

  • View the call stack at any point in time, giving you a context for your current stack frame.
  • Step into libraries that you are not able to re-compile for the purposes of adding traces (assuming you have access to the debug symbols)
  • Change variable values while the program is running
  • Edit and continue - the ability to change code while it is running and immediately see the results of the change
  • Be able to watch variables, seeing when they change
  • Be able to skip or repeat sections of code, to see how the code will perform. This allows you to test out theoretical changes before making them.
  • Examine memory contents in real-time
  • Alert you when certain exceptions are thrown, even if they are handled by the application.
  • Conditional breakpointing; stopping the application only in exceptional circumstances to allow you to analyse the stack and variables.
  • View the thread context in multi-threaded applications, which can be difficult to achieve with tracing (as the traces from different threads will be interleaved in the output).

In summary, print statements are (generally) static and you'll need to re-compile to get additional information if your original statements weren't detailed enough. The IDE removes this static barrier, giving you a dynamic toolkit at your fingertips.

When I first started coding, I couldn't understand what the big deal with debuggers was and I thought I could achieve anything with tracing (granted, that was on unix and the debugger was GDB). But once you learn how to properly use a graphical debugger, you don't want to go back to print statements.

LeopardSkinPillBoxHat
The dynamic debugging aspect is a good point.
Bill Karwin
Handier than watches, you can also hover over a variable name while stepping through code and you get a tooltip of the value. You can even change that value by clicking into the tooltip. That ruxx0rs.
stimpy77
The bulk of these are properties of interactive debuggers, with or without a IDE. I.e, everything on that list (with the possible exception of change code in place) is possible with GDB.
dmckee
Yes, but the OP asked "What makes IDE debugging tools so much more effective than thoughtful use of diagnostic print statements?". I was comparing IDE debugging tools vs. print statements, not IDE debugging vs. console debugging.
LeopardSkinPillBoxHat
darron
As of PHP5 you can also print a call stack any place you see fit, just use "new Exception()->getTraceAsString()". Developing server-side apps there are cases when print or mail beats any debugger.
inkredibl
+2  A: 

This is what I use most on VS.NET debuggging windows:

  • Call stack, which is also a great way to figure out someone else's code
  • Locals & Watches
  • Immediate window, which is basically a C# console and also lets me change variable contents, initialize stuff etc
  • The ability to skip a line, set the next statement to be executed somewhere else
  • The ability to hover over variables and have a tooltip showing me their values

In summary, it gives me a 360 degree view of the state of my executing code, not just a small window.

Never found a book teaching this kind of stuff, but then again, it seems to be quite simple, it's pretty much WYSIWYG.

rodbv
+1 for at least addressing the part of my question regarding resources to learn more.
Bill Karwin
+4  A: 

One reason to use the IDE might be that modern IDEs support more than simple breakpoints. For example, Visual Studio offers the following advanced debugging features:

  • define conditional breakpoints (break only if a condition is met, or only on the n-th time the statement at the breakpoint is executed)
  • break on an unhandled exception or whenever a (specific) ecxeption is to be thrown
  • change variable while debugging
  • repeating a piece of code by setting the next line to be executed
  • etc.

Also, when using the debugger, you won't have to remove all your print statements once you have finished debugging.

M4N
Those are good examples. I guess I have just never seen a decent tutorial or article showing how to use them. Also I rarely use VS or other Microsoft solutions.
Bill Karwin
The chore of removing debug code is valid, though I can often just do "svn revert" to get rid of it.
Bill Karwin
#ifdef DEBUG printf("variable whatever is now %d\n",var); fflush(stdout);#endif
Arthur Kalliokoski
+1  A: 
  • A debugger can attach to a running process

  • Often easier to debug threaded code from a debugger

Mitch Wheat
A: 

It's not just debugging. An IDE helps you build better software faster in a lot of ways:

  • refactoring tools
  • intellisense to make api's more discoverable, or remind of exact spelling/case of familiar items(not much use if you've used the same system for 15 years, but that's rare)
  • save on typing by autocompleting variable and class names
  • find certain kinds of errors before you even start to compile
  • Automatically jump to variable/method/class declarations/definitions, even if they're not in the same file or folder.
  • Break on unhandled and handled exceptions

I could go on.

Joel Coehoorn
errr... that was not the question.
vmarquez
Those are all good features of IDE's too, but most of them have to do with what could be termed "smart editing." I understand the value of a smart editor, but visual debugging was what I meant to ask about.
Bill Karwin
Although I do understand that having the debugger integrated with the smart editor and all those other features has value.
Bill Karwin
+4  A: 

Off the top of my head:

  1. Debugging complex objects - Debuggers allow you to step deep into an object's innards. If your object has, say, an array of array of complex objects, print statements will only get you so far.
  2. The ability to step past code - Debuggers will also allow you to skip past code you don't want to execute. True, you could do this manually as well, but it's that much more code you have to inject.
Kevin Pang
But I can do both of these things now using "manual" debugging... whether by injecting code or figuring out a maze-like series of IDE menu choices.
Bill Karwin
Yes, you can. But do you really want to? You asked for reasons why using an IDE to debug is better, not for things that are ONLY provided by an IDE.
Kevin Pang
Fair enough. Assuming one learns the menu incantation to use those features, then subsequently they are easier than having to write new debugging code every time.
Bill Karwin
+12  A: 

Here's one thing that you definitely cannot debug with "print" statement, which is when a customer brings you memory dump and says "your program crashed, can you tell me why?"

galets
+2  A: 

Because debugging multi-threaded applications with print statements will drive you bananas. Yes you can still do it with print statements but you'd need a lot of them and unravelling the sequential print out of statements to emulate the multi-threaded executiong would take a long long time.

Human brains are only single-threaded unfortunately.

DarkwingDuck
Yeah, one could prefix print strings with the thread number or something, or format the output in columns by thread (if there aren't too many). But I get your point.
Bill Karwin
One more thing to keep in mind is that sometimes the print() statement synchronizes threads. I saw once an issue where with debugging logs enabled the app was running okay, but after disabling them it crashed instantly and the thing we figured out was that the app was synchronizing on prints and that caused it to function correctly.
inkredibl
Actually, it has been my experience that a good log library and some cleverly formated print (non syncronized) statemens are sometimes the ONLY way to debug (and understand) some killer multi-threaded bugs. Breakpoints (and extra debug symbols added by the compiler) can change the environment of the bug to the point where it is impossible to find/reproduce/understand the race condition.
Radu094
+4  A: 

I think debugging using print statements is a lost art, and very important for every developer to learn. Once you know how to do that, certain classes of bugs become much easier to debug that way than through an IDE. Programmers who know this technique also have a really good feel of what's useful information to put in a log message (not to mention you'll actually end up reading the log) for non-debugging purposes as well.

That said, you really should know how to use the step-through debugger, since for a different class of bugs it is WAY easier. I'll leave it up to the other excellent answers already posted to explain why :)

rmeador
Agreed, and thanks for the perspective. Just because advanced visual debuggers are useful, does not mean they're the best choice for all tasks. Just like any tool, they have their sweet spot.
Bill Karwin
Agree on that, using print is an important skill. Saved me lots of times when I've only had a limited toolset where it was just possible to edit a file and run it (that's especially true for web development).
inkredibl
Also, using print is a MUST if you are fighting multithreaded race conditions. It's practically impossible to find these bugs using a breakpoint IDE debugger.
Radu094
+6  A: 
  • Print statements all through your code reduces readability.
  • Adding and removing them for debug purposes only is time consuming
  • Debuggers track the call stack making it easy to see where you are
  • Variables can be modified on the fly
  • Adhoc commands can be executed during a pause in execution to assist diagnosing
  • Can be used IN CONJUNCTION with print statements : Debug.Write("...")
DarkwingDuck
Thanks for that list. Not all those points are compelling advantages of visual debugging. E.g. I can print a stack trace pretty easily in many language environments.
Bill Karwin
for #2: connecting a debugger to the server may be even more time consuming at times :)
inkredibl
+2  A: 

Advantages of a debugger over a printf (note not an IDE debugger but any debugger)

  1. Can set watchpoints. This is one of my favourite ways of finding memory corruptions

  2. Can debug a binary that you can't recompile at the moment

  3. Can debug a binary that takes a long time to recompile

  4. Can change variables on the fly

  5. Can call functions on the fly

  6. Doesn't have the problem where debug statemenets are not flushed and hence timing issue can not be debugged acuratly

  7. Debuggers help with core dumps, print statements dont'

hhafez
Yep; good points!
Bill Karwin
+2  A: 

One thing that I'm surprised I haven't seen in another answer is that the 2 debugging methods are not mutually exclusive.

printf debugging can work quite nicely even if you're using a standard debugger (whether IDE based or not). In particular with a logging framework so you can leave all or most of in the released product to help with diagnosing customer problems.

As noted in pretty much all the other answers here, the key nice thing about a standard debugger is that it allows you to more easily examine (and potentially change) the details of the program state. You don't have to know up front what you might want to look at - it's all available at your fingertips (more or less).

Michael Burr
One other answer included the not-mutually-exclusive point, but it's well-taken.
Bill Karwin
+2  A: 

Since you asked for pointers to books... As far as Windows debugging goes, John Robbins has several editions of a good book on Windows debugging:

Debugging Applications for Microsoft .NET and Microsoft Windows

Note that the most recent edition (Debugging Microsoft .NET 2.0 Applications) is .NET only, so you might want an older one (like in the first link) if you want native code debugging (it covers both .NET and native).

Michael Burr
Thanks for the book tips! I rarely use develop with the Microsoft platform, but I appreciate the references.
Bill Karwin
+2  A: 

I personally feel the answer is as simple as "A integrated debugger/IDE gives you a wealth of different information quickly without the need for punching in commands. The information tends to be there in front of you without you haven't tell it what to show you.

The ease in which the information can be retrieved is what makes them better than just command-line debugging, or "printf" debugging.

OJ
That's a good summary or general statement, matching the specific examples many other answers provided.
Bill Karwin
Cheers Bill. I feel that arguing feature vs feature is pointless as most of the time you can do what you need to do in both types of debugger. Integrated ones just make the process a lot simpler (if they're done well, as in the case of VS).
OJ
+1  A: 

With an IDE debugger you can see the values of ALL the variables in the current scope (all the way up the call stack) whenever you halt execution.

Print statements can be great but dumping so much information to the screen at any given place can produce a whole lot of print statements.

Also, many IDE debuggers let you type in and evaluate methods, and evaluate members while you are halted, which further increases the amount of print statements you'd have to do.

I do feel that debuggers are better for some languages than for others however...

My general opinion is that IDE debuggers are absolutely, amazingly wonderful for managed languages like Java or C#, are fairly useful for C++, and are not very useful for scripting languages like Python (but it could be that I just haven't tried a good debugger for any scripting languages yet).

I absolutely love the debugger in IntelliJ IDEA when I do Java development. I just use print statements when I use Python.

TM
Yep, I agree that a dynamic language allows you to skip the recompile step. You can just add another diagnostic print and go. I can imagine a dynamic debugger saves you more time if you have to recompile after every such edit.
Bill Karwin
+1  A: 

As someone said above: Debugger != IDE.

gdb and (back in the day) TurboDebugger (stand-alone) work just fine for the languages they support[ed], thank you. (or an even older technology: Clipper debugger linked into the xBase executable itself) -- none of these required an IDE

Also, though C/++ coding is more rare, printf statements sometimes mask off the very bug you are trying to find! (initialization problems in auto vars on the stack, for instance, or memory allocation/alignment)

Finally, as others stated, you can use both. Some real-time-ish problems almost require a print, or at least a judicious "*video_dbg = ( is_good ? '+' : '-');" somewhere into video memory. My age is showing, this was under DOS :-)

TMTOWTDI

A: 

In addition to much of what the other posters have said, I really like stepping through one line at a time along with the computer, as it forces me to think about one line at a time. Often I will catch the bug without even looking at variable values simply because I am forced to look at it as I click the 'next line' button. However, I don't think my answer will help you, Bill, because you probably have this skill already.

As far as learning resources go, I haven't used any -- I just explore all the menus and options.

drhorrible
+2  A: 

Is this even real question from real programmer?

Anyone who spent even 5 mins debugging with print statements and debugging with IDE - it will OCCUR to him/her without even asking!

This is a funny question coming from someone with a moniker of "Annon".
Bill Karwin
A: 

I've used both prints and IDEs for debugging and I would much rather debug using an IDE. The only time for me when that doesn't work is in time critical situations (like debugging online games) where you litter the code with print statements and then look at the log files after it has gone horribly wrong. Then if you still cannot figure it out, add more prints and repeat.

KPexEA
A: 

Just wanted to mention a useful feature of a console debugger vs printf and vs debugger in an IDE.

You can attach to a remote application (obvioustly, compiled in DEBUG mode) and inspect its state dumping the debugger output to a file using POSIX tee utility. Compared to printf, you can choose where to output the state in run-time.

It helped me a lot when I was debugging Adobe Flash applications deployed in an agressive environment. You just need to define some actions that print required state in each breakpoint, start the console debugger with fdb | tee output.log, and walk through some breakpoints. After that you can print the log and analyse the information by thorough comparison of the state in different breakpoints.

Unfortunatelly, this feature [logging to a file] is rarely available in GUI debuggers, making developers compare the state of objects in their head.

By the way, my opinion is that one should plan where and what to debug before staring a debugger.

newtover
Thanks! But I'm not sure I agree that GUI debuggers lack remote debugging features. In fact, most do have this capability, but it's kind of a pain to set up. Anyway, I wonder if you have checked out DTrace - it sounds like you would like it.
Bill Karwin
@Bill Karwin: I meant the capability to log to a file =)
newtover