Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Do people really use a debugger ?

This is a serious question because in 5+ years of programming I have never used a debuggers. The only time I used a debugger was when I was learning to program and to trace out for loops.

Now I just use print statements and read code to figure out what’s going on.



Yes, absolutely, it's an indispensable tool - and I've been doing this software gig since 1990. Some languages, like JS and Python which are quickly interpreted, are amenable to printf debugging, while others, like C++, C, Go, really benefit from debugging. A debugger is your best bet at debugging multiple threads, for example, especially since you can pause them at strategic locations to recreate a race condition. This is really difficult with printfs.

The world of JS development has tremendously powerful live runtimes/debuggers in the browser developer tools, those are a fine example of what a debugger can be.

I write go using Goland by JetBrains, which uses Delve under the covers as a debugger. Compared to dbx (which was amazing), gdb, etc, it's deficient, but better than nothing.


How do you know how you got to that point in the code without a debugger? What's the call stack like?

How could you debug a call in a DLL that is being loaded by your program if you do not use a debugger?

It might be alright for tiny programs but it's essential for "big" applications.

printf'ing isn't going to help with 2 million+ lines of code or where there's a leak somewhere in that code (eg. someone else wrote some bad code or bad reference counting and didn't release when they should, eg. in COM wrappers in Windows), or someone is double-freeing some memory or trampling on memory and you need a hardware breakpoint to know what is modifying that memory at any given point.

This doesn't affect just compiled languages either - how would you know what is constructing this object, for example? https://github.com/magento/magento2/blob/420a8b6209a4e62ede9...

EDIT: I say all this in a generic "use of debugger" sense, not a Go-specific debugger usage.


I step through almost every line of code I write in a debugger. I'm pretty visual based, and that combined with the action of clicking through forces me to slow down and really think about what my code is doing. Whenever I open the debugger, I find bugs that I can fix! :P

I've heard it said that there are two types of programmers: those that stare at their text editor all day, and those that stare at their debugger all day.


When I write a new unit test I pretty much always step through it in a debugger to make sure it is doing what I think it is doing.


Yes! Try it!

I often find myself working on a legacy codebase. The application will enter a state that I don't think should be possible. The debugger can usually help me figure out how that happened.

It's worth mentioning that debuggers are less essential in languages like Go where the control flow is purposefully very straightforward. I often debug Python and end up being totally surprised to see the execution jump somewhere else because of a decorator.


I believe Rob Pike and Ken T are firmly in the 'add prints' and think camp rather than use a debugger so you're in good company.


Rob Pike has definitely used a debugger: http://www.informit.com/articles/article.aspx?p=1941206

Preferring logging statements is one thing, never having used a debugger is another.


It's as though you didn't even read the very article you linked


It's as if you didn't read the comment I wrote and started foaming at the mouth at the chance to say RTFA as is HN tradition. (Or didn't read the article closely enough yourself)

He said explicitly, he used a debugger.

He came to understand the value of having a proper mental model of your code, but the comment I replied to said they had never used a debugger.

My comment was about the difference between knowing how to problem solve without a debugger, and straight up never having used it

There's nothing wrong with having more tools in your toolbox


> but the comment I replied to said they had never used a debugger.

Except it doesn't say that.


> This is a serious question because in 5+ years of programming I have never used a debuggers. The only time I used a debugger was when I was learning to program and to trace out for loops.

They're saying it themselves, "yeah technically once I used it when I was figuring out how for loops work".

I wouldn't say I've ever written a Brainfuck program even though once I messed around with a hello world on an online interpreter

Leave it to people here to say a comment doesn't say literally the exact words it says

-

The spirit of multiple replies, not just mine is debuggers are an option you should at least be familiar with before tossing aside, even if you do end up not needing them


Except that is not the comment you replied to.

> I believe Rob Pike and Ken T are firmly in the 'add prints' and think camp rather than use a debugger so you're in good company.

And that comment doesn't make any mention of Rob Pike never having used a debugger.


Except it is because this is a comment chain...

None of our comments exist in a vacuum.

-

Person A says: I never used a debugger

Person B replies: You're in company with Rob Pike on that

I reply to Person A and B: Yeah but even Rob Pike uses debuggers

-

The fact I have to spell this out is appalling.


Hint: the word rather

It's a preference not an absolutism.


It's the preference of the people referenced by Person B.

Person A the word _never_, the definition of absolutism.

You're literally making my point, a preference towards not using debugger not a limitation, an absolutist approach of never having used one professionally could be.

It's not like I said "OMG go use one right now or your career will fail" either before you latch onto that too. I said even those guys with a preference away from them, have used them professionally

Didn't think I'd be spelling out 1st grade reading comprehension on HN but here we are.

Why this sudden increase who think turning off their critical thinking skills to go "gotcha" because you didn't write out your comment like a thesis is something positive?


Really depends on your compile->deploy->launch iteration time.

Printf'ing your way to victory works but I'm easily 5x faster with a debugger.


To give an opposite metric, on one of the C++ software I develop the "add printf, compile, and run" takes in average 1/2s while it take sometimes up to a minute to load it in gdb or lldb. Which sucks because a lot of things are incredibly easier with a debugger.


That's very unusual, is it an embedded environment? I'm used to C++ taking much longer than other languages to compile, which in turn discourages printf debugging.


not at all, standard Qt desktop software - when split correctly into object files and shared libraries the incremental build time in C++ can be very fast (also, being on linux and using lld as a linker helps tremendously, building on windows is on average 3-5 times slower for me, and lld links in the bat of an eye compared to bfd (GNU ld) and gold)


You're right. But you need to have been exposed to a good debugger before you understand this. Preferably you also have had a colleague that was proficient in it to get you started.


> Now I just use print statements and read code to figure out what’s going on.

Print is worse and more work. You should set one (or several) breakpoints and then debug, which replaces possibly many run/debug loops at once. You also have no chance of accidentally committing a print statement.

Hearing that people don't use debuggers feels like hearing that someone uses a screwdriver instead of a drill that someone gave them for free and is just sitting in the garage, untouched.

There are literally no drawbacks to switching to a debugger.


> You also have no chance of accidentally committing a print statement.

Debuggers are ephemeral---unless they are "reversible", which is a subject of ongoing research. You can't replace logging with debuggers, and some print statements used for debugging are in fact better described as post-hoc logging. On the other hands, print statements do change your program and can mask some other problems especially in multi-threaded programs.

> There are literally no drawbacks to switching to a debugger.

Only for properly prepared environments. In some environments enabling a debugger itself can be annoying or even close to impossible (for example, some non-native socket-based debuggers tended to be fragile). I use debuggers when I can, but being able to not rely on debuggers is useful from time to time.


You seem to have inferred two straw-man arguments from my comment: 1) that people should stop logging, and 2) that debuggers can be used in 100% of cases.

> You can't replace logging with debuggers

I never suggested this. I only discussed whether to use printing or debuggers for debugging.

> Only for properly prepared environments

Of course, but these are the vast majority. Most devs are working with Java, Python, C#, TS/JS, Visual Basic, Go, or some combo. All have debuggers.


While I meant not to fully refute but rather to build upon your statements, some clarification seems necessary:

> I never suggested this. I only discussed whether to use printing or debuggers for debugging.

Yes, but I specifically mentioned some usefulness of printing for debugging ("post-hoc logging"). Printing can be used both for debugging and for logging simultaneously, and many debugging prints can be readily converted to actual logging. As far as I know there are no widespread equivalents in debuggers---but please let me know if any, I'm genuinely curious.

> Of course, but these are the vast majority. Most devs are working with Java, Python, C#, TS/JS, Visual Basic, Go, or some combo. All have debuggers.

Their quality wildly varies though, and they are especially fragile when multiple languages or environments are in play. In my recent case, Visual Studio 2017 froze when debugging mixed C++ & C# codebase. I tried a lot, but eventually I didn't want to investigate further and decided to use print debugging for the moment. It was finally fixed when I and my team upgraded to VS 2019, I still don't know why it didn't work and it fixed itself.


Sure you can, thanks to OS trace points like ETW.


I believe you do not always keep ETW or similar instrumentions on, while logging is typically always on.


Logging is also not always on, unless one has CPU cycles to burn.


Then probably I was talking about something else. I meant persistent logging for later inspection, not ephemeral logging for one-off debugging (yes, it is confusing...).


My impression has been that developers way too often rely on the subsequent use of the debugger when writing code. It’s like, “I don’t really know what I’m doing, but the debugger will help me understand my code... Oh, what a piece of crap I wrote! Let me start over...” Looks almost like people are debugging themselves.


They're much more useful in maintenance environments where people have already written a million lines of code before you got there. Of course you have no idea what they've done. After a few years they probably have no idea either. You can go grepping in the codebase, but the sheer speed of asking the debugger "how did I get here?" is hard to beat.

They're also useful in layered environments. Sometimes it's a bug in other people's code and you need to get in there to find out what's happening. When all you have is disassembly, and can't readily insert print statements, the debugger is absolutely invaluable. One of my own "debugger greatest hits" was finding a bug in Windows CE stack unwinding this way.


For me, it's almost always been for understanding other people's code, especially poorly documented third party code internals.


Exactly, the more sophisticated tools we have to manage incomprehensible programs, the worse they get in terms of maintainability.


It's simpler to click a few lines of code, get the entire program state or a selected subset, and then get a perfectly line by line granular understanding if desired, then to write a bunch of print statements. The only reason printlns would seems easier is because it takes s bit more time investment to learn debugging tools.


How do you deal with multothreaded debugging?

In my ide I can see all threads, I can freeze and unfreeze threads as I want, I can run a threads to the same point. All while inspecting the variables in use.

Or pausing code and seeing the whole call stack, having it navigable by just clicking.

This would seem a nightmare with print debugging!


This is a hard question to answer easily, IMO. I find that Java folks tend to overuse the debugger, spending 20 mins stepping through something that a simple value print would have solved.

That said, some code -really- needs a debugger. You can theoretically spend hours adding prints everywhere, but even that pales in comparison.

In short, I find that the need for a debugger is rare, but when you do need it, it's irreplaceable.


If you know where something is going to go wrong and strategically put a print statement, how is that better than just putting a breakpoint there?


There's literally no difference between a print and a breakpoint except that the print you actually have to write code while a breakpoint not only do you don't have to write code... you can see the entire program state.

There is literally no argument here. Debugging with breakpoints is categorically less work.

When you see people stepping through code it's because they don't know where the error occurred. It's the equivalent of putting print statements everywhere. You tell me which one is better.... littering your code with print statements? or breakpoints?


Lots of reasons to love a visual debugger:

- Easily set breakpoints and localize faults quickly.

- Enter the debug shell and evaluate statements based on the current program context.

- Tinker with variables at runtime and see how the code responds.

- Conditionally catch things that are going wrong and evaluate program state at the time.

- Simulate difficult-to-reproduce things like race conditions by messing with program state.

- Use it like a CLI to do stuff from the program, like send requests using the actual program code.


I do use a debugger.

A debugger is not just useful to debug. I've found it a joy to actually be able to step through every step and see e.g. a request being transformed through the different libraries and middlewares. In Goland, you can even step into the stdlib!

I will admit there a few "blind spots" but 99% of the time, a debugger is a super fun way to understand your code rather than inserting print statements everywhere.


Yes. Especially if the debuggers are easy to use and aren’t just gab-style shells.

I can definitely lived without a debugger, I’ve done it before and you get used that after awhile. But given the choice between a programming experience with a good graphical debugger and one without, the former will almost always win out.


"Do people really use a debugger ?"

As with many other perennial programming debates, I think we underestimate the diversity of our experiences when having this debate. There are codebases that debuggers don't really help that much on, perhaps because they're technically very difficult to get running, or perhaps because they were written in such a way as to not really need them very often.

There are other code bases where debuggers are a necessity.

Some of those considerations are not even strictly speaking in the code themselves, but related to the code + developer; for instance, I really love debuggers for codebases I don't understand because I just came to them. You can read the code all you like, but until you watch it run, you don't realize that this one if clause that you kind of skimmed over actually invokes an entire chunk of code you didn't even know existed, etc. Whereas someone intimately familiar with that code may not need the debugger so much. Any sort of recursive data (parsing, HTML nodes, etc.) is a pain to deal with in printf debugging too because you either fail to dump out enough context to understand where you really are, or because you dump out so much context that you drown in it.

My call is that A: they're absolutely indispensable tools that you should have in your toolbelt so that you don't hesitate to use it when you need it, but at the same time B: you should try to avoid depending on them, because a codebase that you can't handle without a debugger is a code base that you can't understand, and that's bad.

I very deliberately say "should try", because it's not always practical; maybe you're just visiting this code base and have no reason to understand it, or maybe it's just intrinsically too darned large to understand, etc. But you should still strive to not need debuggers to follow subtle, complicated code, but make your code do what it says it does and no more. (e.g., stop using globals, don't write code that tries to figure out what lies to tell to other bits of code to make them coincidentally do what you want, etc.) I also say avoid "depending" on them, because if you don't depend on them, you can use it freely. I've only used a Go debugger a handful of times, but each time it saved me a ton of time. But the codebase in question remains comprehensible and straightforward, because I don't make skilled use of a debugger a prerequisite for following it. (I've inherited other code bases which do.)


> As with many other perennial programming debates, I think we underestimate the diversity of our experiences when having this debate. There are codebases that debuggers don't really help that much on, perhaps because they're technically very difficult to get running, or perhaps because they were written in such a way as to not really need them very often. There are other code bases where debuggers are a necessity.

This is absolutely true and very wise; there are a lot of strange kinds of programming environment out there, and we need to be aware of the full spectrum of tooling possibilities. And failure possibilities.

The worst environment I ever had to deal with was a strange embedded one where my code ran as a subprocess of a 3G module. There was a single-step debugger but not a proper JTAG one - so if it crashed, the device reset rather than dropping you to a debug prompt. Printf was sort of possible, but over buffered USB - and if the device crashed, it lost the last few lines in the buffer which would have told you what the crash was. I ended up leaving a breadcrumb trail in bits of memory that were known not to be zeroed on boot.


Using a debugger means that, when my inspection shows nothing wrong with one value, I can immediately check out if other values are wrong.

Whereas with a print statement, I need to change code and then shutdown and rerun the program. The feedback loop of a debugger is just a lot shorter.


>Now I just use print statements and read code to figure out what’s going on.

So, instead of using tool created with debugging in mind, you prefer to edit code in order to achieve "tool that helps you debug"?

what you do if you want to check what's the result of e.g "array[9]"? you write printf(array[9]) instead of use evaluate expression at runtime?

I see no point in that


I did not for the first 10 years :)

These days I feel completely disadvantaged without an interactive debugger (such as gdb, msvc or a good repl)


I don't usually use debuggers in functional programming languages. Since it's mostly expressions I usually use REPLs.

But for imperative languages like Go, a fast and good debugger can boost up productivity a lot if properly used, it's basically a REPL for imperative languages - since imperative languages mess with the ordering and the environments much more than functional languages.

Instead of inferring how to code would be executed, you would debug at reasonable places, know how it executes and play with it directly with some expressions. It's more about the feedback speed.

Only using print it's not sufficient because there are a lot of data structures that are too large to serialize. Or like functions that are not serializable at all, you have to reference it in the debugger or it doesn't really help.


Maybe you don't have the code.


Seems most people here assume debugger is synonymous with source debugger.


Some debuggers will disassemble (to machine or byte code) code without source.


It depends on the language. I've used debuggers in java, much less in c++, and hardly in go. I feel there is not much of a need in go for debugging, writing good tests and the occasional log/print statement do fine.

Java, often having more complicated structures and layers (more due to the culture, one could write more go-like simpler java as well) is more reliant on debugging. More dynamic (less predictable) languages such as python even more.


My debugger usage pattern varies between languages. For C# I rely heavily on the debugger because it is just so easy and pleasant to do so. For Go using GoLand I use the debugger regularly, but I expect that it won't be quite as versatile as debugging C#. For Python or JS I find it easiest and most intuitive to just print-debug for everything.


You can't use print statements in external code like libraries.


Depends on the language. Python? No. C++ yeah, occasionally.


A debugger session is the equivalent of N runs with different prints and value changes. I do not consider I can work seriously without a debugger.


I used to use one a lot, in python. My go code compiles and runs so fast that I don't really need one, though.


How do you do that with a Production system ?

That's where debuggers are essential.


?

I'd hesitate to stop the world in prod.

In prod, logging is usually the answer. (Or OS-level tools.)

On JVM (and I expect all other major platforms) you can tune logging at runtime so just leave the statements in as long as the don't compute anything.


Especially on JVM, conditional breakpoints are really nice for this. (And at least most classic Java-Webservers are really compatible with this approach)


Core dumps are quite useful in production, and they pretty much require a debugger.


I see. That makes sense. To be honest I (almost) never work at that level so I only thought about live debugging.

My bad.


Agreed, debuggers can be nice to have but they are mostly a crutch.... Write modular code with unit tests and you find your need for debuggers is really a rarity


Not every codebase you are working with (or would be working with) has unit tests.

Sometimes you’ll inherit such a project from a dev who left and you would be begging for a debugger.

Otherwise failing that, then the rewrite begins... Debuggers save us that effort in such a codebase.


This. Only time I use debugger working on C# is on crash dumps.


>Do people really use a debugger ?

Absolutely; everything from libraries, language development, even in REPL languages like J and R, I use debuggers all the damn time, native J/R/whatever, GDB, the whole lot. If you deal with hairy issues, there's no way of solving the problem with print statements, and if you're used to them, they're a lot more productive. You just have to pay the toll of learning the debugger.

I haven't uncorked any golang in a long time (~5 years), but I do remember thinking WTF regarding the debugger. I think the idea is to write enough unit tests you don't need the debugger so much. Seems questionable, but what do I know; Google would never hire me. Otherwise I liked golang a lot as a very pragmatic language and ecosystem. I had wished the GC was optional somehow to replace C/C++ tier "systems" stuff, but whatever; it's a fine successor to Java type things.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: