How Would You Improve Today's Debugging Tools?
redelvis asks: "I recently came across an article by MIT's Media Lab on 'The Debugging Scandal and What to Do About It'. It's a few years old now, but it really got me thinking about how little the debugging process has improved over the last 5,10 or even 30 years. I have developed applications using modern IDE debuggers such as Borland's JBuilder, Microsoft's Visual C++, as well as standard tools like gdb and jdb. Despite the slick graphical interfaces, nice thread stack traces and local variable browsers, I still make sure I have on hand plenty of notepads, graph paper, pens and pencils so I can try to build up a picture of what state the program is in and to help me play detective in pinpointing what is going wrong with my (or other peoples) programs. Do other developers have similar problems? Do they find modern IDEs and debuggers have shortcomings in helping track down bugs? What would make a better debugger? Why do you think so much effort been invested in areas such as advanced modelling tools but so little in improving debugging tools?"
Why do you think so much effort been invested in areas such as advanced modelling tools but so little in improving debugging tools?
Easy. As anyone who's ever tried to use software knows, nobody uses debugging tools anyway.
-JDF
Project Builder absolutely sucks for debugging on its own. But, I use it for break point management, but from there I use the GDB console it has. I know dick about getting gdb upto that point, but PB does it nicely. Then I can use p for a normal inspection, and po for an object inspection. I like it. If it weren't for the GDB console, PB would really suck debugging. But with it, it rocks!
What we see depends on mainly what we look for. -- John Lubbock Now search for that bug slave!
Dont debug.
Eventually someone else will find the bugs and fix them for you at their own expense.
This is how the Open Source programming model works.
I don't need no instructions to know how to rock!!!!
But I'd like to be able to create 'conditional' breakpoints (i.e.: stop at this line when i==47).
Other than that, I'd like generalized hot-swapping of code and 'step back' (which I don't know if it's always factible); or at least be able to view a variable's history.
Shame that my IDE of choice (Eclipse) doesn't (AFAIK) support those.
Project Builder is meant to integrate (as you said, through breakpoint control) with GDB. It is not meant to perform debugging on its own.
It's a wonderful development environment -- Project Builder for the code, Interface Builder for the GUI, and GDB for debugging.
Cretin - a powerful and flexible CD reencoder
Doesn't it make you feel good to know that our freedoms are protected by politicans, lawyers and journalists.
Developers, developers, developers, developers.
It take more faith to believe in evolution than it takes to believe in God
One of my biggest problems with people on my current project is the lack of knowledge of how to use even the most basic tools. We program in C++ on Unix and many developers find calling up dbx to be a chore and, even when they get dbx up, have trouble using it. We have many other tools, ddd, other graphical debuggers but people just don't use them, relying on printfs and couts...
main(i){(10-putchar(((25208>>3*(i+=3))&7)+(i ?i-4?100:65:10)))?main(i-4):i;}
I'm a total amateur, but I personally find that software tools can ultimately only go so far in debugging. The two most important debugging tools I'm aware of can't be solved with software: a short break from the project to clear your train of thought, and another set of eyes which might better see what you've overlooked.
----------
Something cleverNo dancing girls!
Add one or two beautiful dancing girls to every debugger, and they'll sell like hotcakes.
Debugging is essentially problem solving and if you don't have well developed skills doing that, then it's not going to be very easy to do. However, every person thinks differently and hence approaches to problem solving varies. It seems to me that although computers can help narrow down the scope of this issue, in the end, it's the brain that is the most powerful tool.
Remember those high school days of comparing the green text on your TRS-80 monitor to the print in your Softside magazine. Now that was fun... har har.
As much as everybody here likes to make fun of Visual Basic, I encourage all to have a look at VB's debugger. While there are a few improvements here and there that could be made, in general it far, far surpasses anything else that I have seen out there. (I have yet to play with VB.net--I am referring here to VB6).
Also, using a debugger often requires learning a new IDE. The best ones are usually integrated with some IDE that I otherwise hate. I understand why that would be the case, but I still hate it. I don't want to learn a new IDE!
--naked
Very popular slashdot journal for adul
All I want from a debugger is to be able to step through code and see values of my variables at certain points and verify program flow.
Most often I'll use it as a tool alongside using printf's or println's and (gasp!!!) just sitting down and reading the code in question.
Debuggers are useful, but I see too many freshouts using them exclusively to fix code, rather than just looking at the code to analyze the design.
The revolution will be televised. Blackout restrictions apply.
Strategically embedded print statements - the time-honored way to find bugs.
That plus printing out and actually READING the code. Amazing what you can find by walking out of range of the screen and keyboard and just reading through the stuff.
I don't know if it's my greatest failing or greatest success as a developer, but I tend to be a println debugger all the way.
Recently I remember seeing some justification/defenses of this technique, I think it's sometimes called "logging based debugging".
When something goes wrong I figure out the related assumptions I'm making, and then test 'em by output to STDOUT or STDERR or a file. It avoids some of the "Heizenbug" problems debuggers can bring on (so long as dumping output can be reasonably expected to be reliable w/o bringing on crossproblems) and by thinking of your assumptions, you're tying into principles similar to "write tests first", part of XP practices.
One set of things this doesn't handle well is memory leaks and bottlenecks and looking out for runaway object creation and the like, but garden variety debuggers usually don't cover that too well either, you need special profiling tools anyway.
SO YOU'RE GOING TO DIE: The Comic for Dealing with Death
Real debugging uses (1) printf calls to trace execution path, dump variables, and detect the crash point down to the nearest few lines (2) eyeballs and brain to spot the goof now its position is locked down. Debuggers are just for the wierdass bugs, and mostly they break differently in those cases anyway, because they're singlestepping not running full tilt.
A good debugger for those cases whern one's needed is DDD.
Make them work better at debugging. What a pointless story/question this is.
Is miles in advance of earlier versions of debuggers. Change code at runtime, you sexy beast.
dominionrd.blogspot.com - Restaurants on
a) it is hard to make money on debuggers
b) making a good debugger is definately not easy
c) many developers prefer puzzling out the code on pen and paper then walking it in a debugger. Quite a few I have talked to believe that they make better code if they can solve the problem without resorting to debuggers. This BTW is why Linus does not like kernel debuggers.
d) most of the debuggers are good enough and as we all know from open source, a good enough solution will live forever. The existence of a debugger that mostly works gives most people a reason to spend their time elsewhere.
In my experience I have truly benefited more from programs like Purify or Insure (and now the great valgrind) than I have from a debugger.
Visual Basic supports a "watch" that allows you to break on condition such as when a variable changes at all or if a variable is set to a certain value. This is beautiful when trying to figure out how the currency value you just had disappeared. Add the watch saying when the currency = 0 and run the app so it breaks at ANY MODULE at ANY TIME.
This saves me time by not having to go into each module and watch the code to see if the value changes.
As for wanted features ( so as to not be totally off topic ) I really can't think of any that I would need per se. Since my favorite language is VB ( watch the flames poor in on that statement ) I have many tools for debugging that are perfect.
From the immediate window so I can run small snippits of code in break mode to the stack and watch windows.
I work with a variety of IDE's and tools so my debuggers range in quality from acceptable to non-existant.
Therefore, I make every effort not to depend entirely on my debugger. I use a combination of assertions, exceptions and logging to make sure that when something goes out of bounds, the reasons and the states are there in black and white.
Yes, it takes a bit longer to code, but it makes testing, debugging and especially exception path fixes much, much faster.
Every time I hear something from the MIT Media Lab, it's a searing indictment of something terribly wrong software engineering or computer science, and how they are here to fix it with avatars or wearable computers or something. And then you never hear about the idea again.
Well howto improve debugging tools.... simply hand them over to the GNOME developers, they know what they are doing first of all the default configuration mechanism get replaced with GConf (Windows Registry) System and then If it's a GUI client, we change the Button Ordering to make the application suck as much as even possible.
ddd's visualization capabilities are terrific. You might be able to get rid of the graph paper.
Why should I have to pay for a debugging tool, or write a debugging tool? I've had the best debugging tool with me all along -- my brain.
http://www.virtualvillagesquare.com/ Online Communities: The Next Generation
I think that very few people use them often enough to justify spending lots of R+D hours+$$$ on the debugging tools. How often do you see "-DDEBUG" in Makefiles? You'd think that if debuggers were so useful, you wouldn't need to switch in debugging code in the app. But many programmers feel more at home locating the bug using printfs or similar, then just reading through the code. Pencil and paper often helps too.
Something I learnt from my BASIC days, which I still use in *sh/Python code is the use of the interactive interpreter (a.k.a. "command line" :-). This is especially helpful when trying to debug someone else's code - you can enter it line-at-a-time and see what happens. Yeah, so gdb can do that. But you think more about the code if you're typing it in yourself than you do repeatedly pressing the "step" key.
I have used debuggers such as disassemblers and monitors as well as gdb, the Delphi debugger etc. While they have uses I just don't find they do anything sufficiently different from manual debugging to make them worthwhile.
There's my £1E-2 :-)
If you're using a language like VB or Delphi debugging is simple and almost inviting. I think that has always promoted bad application design. "Oh, that didn't work. OK, let's try this. Oh, that didn't work. OK, maybe this will work" and so on.
If you're writing applications in C or C++, and especially as you get closer to the system, you learn to be more careful about what your application does because it's very difficult to change direction in mid-flight. It also forces you to think about what you're doing a lot more. I.e., you have to know what you're doing. Impressive concept, but frequently lost on today's "programmers".
IMO, something like the "edit and continue" feature found in modern integrated IDEs like VB is a bad idea.
The best way to learn how to write bug-free code is to NOT use a debugger at all. Every programmer should begin writing code in Notepad or some other basic, no-frills text editor. Just like everyone should learn how to type on a typewriter and not a computer. It forces you to NOT make mistakes, instead of correcting them (you don't have to "debug" a program if you don't put the bugs in in the first place!) It forces you to slow down and think about what you're doing, instead of blasting through a procedure and then run the debugger on it. If everyone programmed for at least a year without ever using a debugger, the quality of their code will improve far greater than any fancy IDE debugger will improve it.
A man's reach must exceed his grasp, or what's an erection for?
I'd make them totally automagic. All you'd have to do is click the icon and it would debug your code. It would fix mistakes without even prompting. It would modify and streamline the code to make it fast and efficient. It would cure all buffer overflows, memory leaks, heap corruptions, everything. It would document the code, line by line in english your mother could understand. It would have a super cool GUI that was easy to understand and showed you a porn slide show while it was churning through the code.
It would be so totally awesome that Microsoft would beg me to sell it to them. But, it would be licensed under the GPLv3, which would be just like a BSD license but, include a clause excluding Microsoft and their affiliates from even looking at the code, much less using it.
It would be the most awesome debugger the planet has ever seen. Yep. That's how I would improve it. Why, what were you thinking?
What's that? I trust Microsoft to run the show!
/sarcasm
Trolling is a art,
Too many people were dependant on them when I took programming classes in college. They'd write code carelessly, and then run it through the debugger, and do exactly what it said, instead of learning to code properly.
It's been my experience that current tools like Visual Studio are just fine. Once in a while maybe a kernel level debugger. Most often bugs are the result of some logic error in some algorithm you just know should be working. And with a little tracing and memory dumps you can find the problem.
However, if the error is such that cannot be tracked down within a reasonable amount of time and isn't confined to a small section of code then I wouldn't consider it a bug but a flaw in the design. A good design would eliminate such difficult bugs and then the smaller ones only need the simpler tools we currently have to track them down.
In my opinion, the advances in modeling tools help reduce the number of potential problems so there isn't as much of a need for advanced debuggers.
I'm sure some will disagree but this has been my experience. I've redesigned sections of code to eliminate an elusive bug and it's made for a more solid application.
Ascalante: Your bride is over 3,000 years old.
Kull: She told me she was 19!
Of course, the problem is, debugging tools will only help you track down bugs that you are looking for - and hence bugs that you know exist.
It is not the case that software companies and the like intentionally release software with no known bugs (cue: microsoft puns) it is they do not know they exist. No amount of debugging tools will help you find these bugs.
The general methodology for many programmers (from amateur to supposedly professional) is to write some code and do a few quick tests. Perhaps throwing in a few -1's and out of range values to check for error checking. The caveat here of course is that these checks don't always apply to a real world bug which the programmer hasn't even contemplated. It is poor planning and bad design that inevitably leads to the bugs - as the author of this post suggests, maybe we should all spend more time with our graph paper and pencils before writing the code.
A debugging tool is there to help fix bugs that you know exist - unfortunately it is often the userbase that has the job of finding them.
mahlen
If you used a Smalltalk debugger, you wouldn't be complaining so much. Give it a try sometime.
I think we will come full cycle on this and start to have success when we are able to peel away the abstract levels of encapsulation and stop attempting to hide the data away by using high level constructs.
I've seen that most of the high level languages (java, Visual Basic, c#) promote RAD via lack of formal trainging. Thus the real problems start to show up when someone who has learned the syntax but knows nothing about how IPv6 packets handle little endian sockets tries to debug a complext multi threaded app and spend all their time basically guessing instead of analytically and systematically debugging the application.
Fred Brooks in the "Mythical Man Month" stated that unless a language is written in the same language that you increase the time to debug it by Olog(n) and that's true today when you look at java (not written in java) or perl or c# as opposed to languages like C and Fortran that are optimzed for debugging by being written in C and Fortran. Much of what Fred wrote about is not pertinat any more that this one still stands the test of time.
Basically it's a low level problem and not a "debugging tool" problem as I see it.
Warmest regards,
--Jack
Wagner LLC Consulting Co. - Getting it right the first time
Having a more interactive development environment makes debuggers much less necessary.
When building the project is expensive, then debuggers really help because it's "cheaper" to fight a debugger than it is add a "printf" into the code.
But when the turn around is very quick, then "printf" and simple functional tests make things MUCH easier.
I haven't used a debugger is years.
The real problem is that the majority of software that is written is fairly lousy. People often code to moving requirements, push code in directions it was never intended to go in, and work with designs that are in desperate need of landing on the compost heap.
Honest debugging is most useful when something is being developed in the first place. Domain knowledge is what is most useful when ancient and decrepit software is being modified to do something it shouldn't.
Software applications should be thought of as prarie lands. From time to time, lightning strikes, and burns out a huge chunk, which is all replaced by newer and healthier stuff. You need talented people to make sure the new code will work well with what's already there - but the end result is that the application will be healthier if frequent refactoring is done intelligently.
Education is the silver bullet.
Best IDE and debugger around, bar none. To be honest, one of the first debuggers which actually works all the way through. You can debug from a POST event on a web page, through the code-behind code, through the middle tiers, and all the way into the stored procedures. Nice.
Debuggers aren't flashy or glamorous. I don't know anybody that thinks debuggers are cool. The tools and pieces of a development environment that are going to catch a programmers eye first are what's focused on most. You look at a nicely developed IDE that's polished and slick, and you'll be impressed. It's eye candy that sells products more than anything else.
Sadly, most -programmers- even look at a development environment's debugger as an afterthought. IMHO, it's one of the single most important tools (if not THE most important) and it's what I check out first.
Have you ever used the Gnu Visual Debugger at the GNAT Libre software developers' site? It's a multi-platform (Linux/Unix/Windows), open-source debugger with a "different view" of the world. Check it out, you may be pleasantly suprised.
1) The ability to set conditional breakpoints.
2) The ability to see not only a variable's current value, but a stack of all of its previous values.
3) The ability to select a variable's previous value and jump to the line of code that set it to that.
4) The ability to change the value of a variable at any point.
5) The ability to add/change code on the fly.
6) The ability to jump into the debugger at any point in the program, even when I hadn't planned to before running it.
7) Auto-logging of method calls and (optionally) variable values, to be started and stopped as I see fit either while stepping through code or running it.
That's all that comes to mind off the top of my head.
"You cannot simultaneously prevent and prepare for war." -- Albert Einstein
... about Debugging Tools. He felt that engineers should just learn to write software without bugs in it.
I wouldn't let the retards at microsoft work on any more code for the IDE. Then at least it wouln't get any worse.
It is simple.
Quality and/or security (which is often the same thing) doesn't pay the bill. Features pay the bill, runaway version numbers pay the bill.
It would be the same in other industries if it weren't for cunsumers' rights and vendor's liability. Unfortunatelly there is no liability for software vendors, so the QA is still in its infancy as it was few decades ago.
Robert
Bastard Operator From 193.219.28.162
What's actually needed is more intelligent languages and automated code checking tools, as well as better code review and coding practices. Strict code review and coding practices help make programming more like a real engineering endeavor, instead of the fly-by-the-seat-of-your-pants garage hack-fest that seems prevalent in a lot of existing code. But, the real challenge is to develop languages with features like the ability to detect potential problems in code using partial evaluation, and alert the programmer at compilation time rather than run time.
Basically, we're still in the hunter-gatherer stage of software development, and the Bug Problem needs to be fixed by a fundamental shift in paradigm that can move us beyond the need to deal with "bugs" explicitly. Until then, a snappier debugger interface and new debugging features will only have marginal impact on the ability to develop fault-free software.
* mild mannered physics grad student by day *
* daring code hacker by night *
http://www.silent-tristero.com
System.out.println(). Works fine for me most of the time. If not, I can print a stack trace and see what's going on...assuming Java, of course.
The only place I've seen that a debugger comes in handy is stepping through poorly understood code. Really, the code should be documented well enough to explain what's going on, but that's rarely the case.
"In a 32-bit world, you're a 2-bit user. You've got your own newsgroup, alt.total.loser." -Weird Al
At some point debugging comes down to, the computer can only do what people tell it to do. A lot of advancement has been made in making it easier for programmers to communicate with computers. Advances are made in methods for reporting just what is being done or why something can't be done. But in the end, the bottleneck is the programmer who has sit down with his pencil and paper and slide rule and figure out, "is this really what I want to tell the computer to do?"
Remove the bugs.
There's an article in the latest issue of Embedded Systems Programming about using visualization tools for debugging. Well worth reading.
-Mark
Debugging is difficult primarily because debuggers do not appear to use any kind of intuition.
Let's say I have a break point on an if statement. The debugger should automatically show me the values of any variables in the condition, as well as the truth values of the individual expressions in that condition.
A debugger should have an "intelligent" step button that steps into code that has debugging symbols, but steps over system calls. It should also automatically skip to the end of loops if desired.
Debuggers should have "sanity" checks for values. Any time a pointer is null, or an long integer is set to some really wild value (like -3492883773642) that is nowhere close to the values that it originally contained, or a string doesn't have a null terminator, the debugger should alert you with a little icon, even if you aren't actively watching that variable.
One thing that sucks about debugging is when programs behave differently in the debugging environment than they do once compiled. We had several problems related to event handling in Visual Basic only occured if the program had been compiled. In debug mode, it worked fine.
Debuggers should keep a "state" history, especially for loops or recursive functions, so you can see the entire progression of a set of variables until the point of failure. This eliminates having to write in a bunch of printf statements to get a snapshot of each loop iteration or function call.
The debugger should be integrated into the IDE so you don't have to switch back and forth. Also, it would be really nice if debuggers executed under some kind of virtual machine that allowed you to more easily freeze execution, rewind it, tinker with it as it's running, etc. Visual Basic allows you to do some of this, but certain code changes require you to restart the whole program. I'd like it if you never had to restart, and the line between "debug mode" and "design mode" were almost entirely blurred.
Just my $0.02.
bytesmythe
Hypocrisy is the resin that holds the plywood of society together.
-- Scott Meyer
As somebody who uses printf, I would like the facility to add printf's retrospectively without having to recompile and re-run the code. printf debugging is great because it can be extremely context sensitive to the state of the program.
Another advantage of printf debugging is that you can compare the behaviour of two similar versions where one displays a bug, and see where the buggy one's behaviour is differing from the working version. Perl is a great tool for accounting for differences which are expected
Other than that, I find debugging on x86 is a pain because the assembler is much harder to read than a RISC instruction set like ARM. I don't know what I'll do if I ever have to debug something on IA64 :)
I did see a demo of a Java debug system which generated a log during execution and allowed the user to look at what was the full state of the program at any point during its execution. Very cool.
Sure, we all like debuggers with conditional breakpoints and backward stepping, but the more you add to the debugger the less opportunity you will of finding the bug (unless its a 'smack in the face' bug).
The only way of truely solving bugs is to know exactly whats going on in the code (and, also as important, is knowing the language, operating system, and the things going on in the background. IE - in Java, although it appears as if you aren't dealing with pointers, you are, and you should treat all objects like a reference, cause that's what they are). If you can't study the code (cause it was written poorly), it is a terrible terrible thing, because most bugs are not just one line fixes (and even those that are require you to know exactly what all is going on around them).
"Cherry picking" (just tuning up one line and "guessing" that that's the problem) is what most 'amateurs that taught themselves coding' do, and on major/enourmously large projects, this will do nothing more than cause trouble.
The best way to beat a bug is knowledge.
Good quote, too many chars. Seriously, the slashdot 120 char limit sucks!
A debugger is going to help you find and fix the bugs that got through:
Studies have shown repeatedly that the cost of fixing each bug increases at each stage. So if you are going to invest $1000 in new development tools, is it more economical to buy tools to detect bugs when they're cheap, or when they're expensive?
The original poster's questions are all loaded with the presumption that something is wrong with using graph paper, pens and pencils.
Why on earth do so many people feel all development tools need to be built into a software debugger or they are inferior???
One great tool he did not mentiong is the napkin.
For embedded programming, logic analyzers will let you store X number of steps before your program crashes. Of course, they cost $80,000, but it's still an alternative for the top 10% of employees of the top 100 tech companies...
Exception stack traces are a godsend.
Jason.
Good example is a damaged database. If you say "You have a damaged record", the customer says, "Well, fix the record and get all my data back!". If you say, "All your data is lost, but I think I can get most of it back if I get rid of this one record.", the customer says "DELETE that record!".
Necessity is the plea for every infringement of human freedom. It is the argument of tyrants; it is the creed of slaves.
And that's his problem - he didn't think.
Interpreted languages like perl or python could highlight bad syntax by running the code you are typing through parts of their own interpreter at given intervals. Kind of like an 'autocorrect' feature in some word processors.
I think I would find it more annoying than helpful.
I used to always lint my C code from Emacs when I was using C all the time. Does that count?
gdb also supports many types of breakpoints. You can use the "watch" command to break execution when a variable changes, or you can set conditional breakpoints (see "help breakpoints" for the options available to you).
The more work goes in before you get to the debugging stage, the less buggy your product will be. A well-designed system does not need as much debugging later. I know I'm idealizing, but I've seen this bear out, especially when version N > 1 comes out and it's been hacked to smithereens because of poor design choices in the previous iteration.
Probably the most amazing bit of self-fulfilling prophecy you'll ever hear on a software project is a manager saying, "We'd better start coding now, because we're going to have a lot of debugging to do."
As for catching things ahead of time, I've always put breadcrumbs in my code to spew to stderr or a Java error console class or wherever. Very easy to #ifdef out later and trivial to turn back on later.
This is not my sandwich.
Simple. Use the debugging tools that come bundled with Ninnle Linux!
printf() ?
>:)
The problem I tend to have with debuggers is that they can only tell you what happened, not how it happened. E.g. I can see that char* is NULL, but how did it get to be NULL in the first place? When did I pass NULL into that function? A debugger won't tell you. About the only thing a debugger is useful for is examining a snapshot of the running process, but then so will a bunch of fprint(stderr,'s.
That, and the syntax for tools like gdb is just awful.
Maybe its just me. I've so used to working without a debugger, I don't think I'd even bother to a learn to use one these days.
Comment removed based on user account deletion
One feature I really liked, that exists in a few places such as VC++ and edebug (for emacs), is the ability to jump around in the code and set values at runtime. You can do a lot with these two features, from running the same code over and over at runtime with different values, to skipping over a part of the code you consider problematic and seeing if it helps.
One of the best debuggers I ever used is what I'm currently coding in - CA Clipper. Does it all, and I use VB 6 as well, so I know this is true.
It's Christmas everyday with BitTorrent.
Been writing code since 1978, and the only debugging tool I've ever needed is:
printf();
Seriously, an over-reliance on debugging tools is something I've *definitely* seen come into this industry.
Bah. Chimps.
; -- the corruption of government starts with its secrets. a truly free people keep no secrets. --
I haven't used a debugger in almost two years. I think the solution to diagnosing problems is to have in place a good logging framework (such as Log4J), which allows you to specify the verbosity of logging per subsystem. (Most people's complaints about using logging is that the noise/signal ratio is often too high to be useful.)
Usually, with a complicated program, it's fairly difficult (in an IDE) to trace the execution flow without stepping into the wrong subroutine or accidentally stepping over the routine you're really interested in. In a lot of cases, it will take more time setting up your IDE or debugger to do what you want, than it is to simply set up useful log statements that capture what you're really interested in. If you set up all your objects in Java to return useful debug strings from the "Object.toString()" method, you don't really need to use an IDE for inspectors or watches: You can customize debug information, avoiding information overload, and allows you to present just the critical data.
For memory profiling (leaks), disassemly, and performance analysis, a proper tool is very worthwhile. And I think that getting a stack trace from a core dump file useful. For everything else, I agree with Linus that debuggers don't really help you be more careful.
You might take a look at GVD, the GNU Visual Debugger,
which can generate graphs of datastructures.
See: http://libre.act-europe.fr/gvd/
You can implement reversibility on a per-thread basis (though that's harder than it sounds, in my experience). For multiple threads, it's basically impossible.
It's much easier to implement back-stepping in a processor simulator or virtual machine than it is in a native-code debugger. Unless you single-step through all the instructions, keeping snapshots of all the relevant state along the way, you can't go back.
And if you do single-step, the performance will likely be so poor that you might as well use a simulator.
-Mark
Debuggers have their place, but in some cases, to have to resort to a debugger can mean that the code is too complicated, or badly designed in the first place. Furthermore, having to use a debugger many times on the same bits of code is a clear sign that the stlye of the code is bug-prone and it should be rewritten.
-- MartinG To mail me: echo kewyjlcxyzvjfxbqwh | tr bcefhjklqvwxyz
So I am not suprised that debuggers still have not gotten anywhere cause general program development has not really evolved as you would expect. We all have lost site of the idea that productivity is total output / total input of the whole team but instead focus on our little part in the bigger picture even if we are screwing up the project in the process.
Almost all comments ignore the main problem with debuggers: they let you verify that a program works correctly for a given input, but tell you nothing about what happens for other inputs you haven't tried. Did you miss something? Are there buffer overflows or security holes? Coverage tools can help, but then you've got to come up with directed tests to reach all of the code, or prove that it can't be reached.
Complete formal verification for large programs is a pipe dream, but there is a lot that can be discoverd through static analysis. Consider Dawson Engler's Meta-Level Compilation project, which automatically found hundreds of errors in the Linux kernel, for an example of what is possible.
Engler and gang have gotten quiet lately, I wonder if they are trying to start a company.
There are other approaches, used in hardware verification, that can mix directed testing with symbolic methods (from a state that is reached in a simulation, can I reach some "bad" state? If so, generate a test vector that takes me there).
While waiting for these tools to be developed, get a four-year old. Let him/her play with your GUI. If it's a Gnome or KDE app, it will probably crash in under ten minutes, because the kid will do things that would never occur to the developer or tester.
One of the reasons debuggers are so far behind, is that they attempt to make the vonNeuman paradigm real for debugging programs.
I write CPU simulators. In this kind of environment, there may be hundreds of threads each performing one little iota of work per (simulated CPU) cycle. When a bug is encountered, the code that encounters the bug is not in any way related to the code that created the bug. And the cod that created the bug may have made its mistake thousands of simulated CPU cycles (billions of actual CPU instructions) before the code that stumbles over the bug-incarnate.
Stack back traces, and other vonNeuman-like debuggers are totally useless in this kind of programming environment. I am simulating real parallel things (circuits) on a sequential turing machine. Its no wonder that a debugger is useless--it is based on the wrong mental model of what I am programming.
I have to build the degugger into the actual simulation code--which I proport--is the right way to debug programs anyway.
New tools come on the market, new people come along, but many things never change. Most people do not code well, they only code well-enough. Programs do not have to work, they only have to work well-enough. There are still plenty of idiots in the business today but there are just more people so the percentage or outright count of people who are incompetent seems to be out-of-touch with what it was 10, 15, 20, ... years ago.
Most people do not even know the first thing about debugging - it's almost a process of trial-and-error, regardless of their schooling, intellect, experience. They make a change, throw it against the wall, then see if it sticks. It's almost like they're wardialers trying to find a magic phone number.
The sad part is their friends, relatives, and people who are lower on the ladder somehow think these people are gods.
And to make it worse, most people, if they've attended college, have taken a few programming classes, or that's all they've taken. Where are the people who have taken a comprehensive scope to approach the industry? A hardware interfacing class, an assembler class where you write your own assembler, a database class where you write your own DBMS, etc. How about a technical writing course? No one says that because you take a hardware class that you have to expect to do hardware on the job, but it provides perspective. The same goes for technical writing.
On top of that, look at the messages posted. 75% of the people can't write complete sentences - it's actually higher than 75%. Poor spelling doesn't mean anyone is stupid. It does, however, indicate they are poor organizers - unable to organize information in their brain, as an example.
I already know most of the people who read this will shred it, but remember this:
"Truth fears no trial." -Thomas Paine
Clippy!
If you mod me down the terrorists will have won
Most programmers use some kind of logging & trace mechanism when debugging. For the most part you know where the problem is located and it takes longer to 'run program to cursor', then do watches on the variables, then it is to just do a log(Level.DEBUG, "variable", var) and run the program.
Using a debugger is rarely more effective. Some situations demand it, e.g. a bug caused by a compiler bug.
Perhaps language & IDE's should concentrate development on helping with the kind of debugging tools that programmers actually use, then sophisticated debuggers.
At the very least using System.out.println() should not be necesary. VB has Debug.print although for various reasons it's really annoying to use. E.g. it doesn't clear itself on every program run.
I use debuggers every day, and find them indespensible for tracking down obscure bugs. (Like the one I just hit a few minutes ago - why does MSVC barf when calling vector::clear? The debugger stops app execution in _free_base() in free.c. This doesn't happen if I recompile using STLPort instead of the default stl library. ) That said, when I don't use a debugger I'm sure I find myself writing more robust code - I'm more inclined to spend more time on proper exception handling, thinking about my design instead of: write, compile, run, oh it failed on line 2493, fix that line, run again, now it fails at line 2547, fix that ....
which results in code that works under the exact set of circumstances that you test it, but has no guarantee as to what will happen if the parameters change any. (And those pesky users always find those annoying 'special cases').
I haven't used it myself, but this debugger for Java allows you to record the execution of your program and play it back again and again to see what's happening, who's setting what variables, etc http://www.lambdacs.com/debugger/debugger.html It appears to be free (as in beer), so there's a bonus for your right there!
subrountins are just hierarchical encapuslations of these with inputs and outputs.
a given subroutine does not "fire" (is called) until all of the input wires have delivered there data. Thus one does not (usually) explicity control the order in which subroutines execute. as long as they have no dependencies (i.e. output wires from one leading to input wires of the other) then they are free to execute whenever their inputs are filled.
to debug in this language one watched the diagram. Graphicaly a value passes down a "wire" like a pig in a python and stops when it reaches an input (or maybe it splits if the wire splits, and goes to more than one input icon). once the subroutine icon has all its inputs filled, it pops open and reveals all the witing in side. the data again passes from the input connectors to the internal wires and so on. once all the outputs are satisfied, the window closes and were back in the original diagram.
you can place text boxes or graphs or chart recorders, or image plots on any wire. these show you the contents or changing contents of the wire in the format if the viewer. e.g. a strip chart recorder plots single or array values on a strip char that scrolls with time so you can watch them change.
you can selectively debug any part of the wiring diagram and let the other perform normally.
The neat part of the language is there is NO SUCH THING as a syntax error, or wrong pointer, or memory location overlap. Indeed there are no variables at all. just wires and controls that inject values into wires or display values in the wires. this makes it very suitable for control systems where those sort of programming errors are undesirable. Better to have wrong functionality that weird unexpected memory errors
the other cool thing about the language is that because it is inherently concurrent and event driven rather than sequenctial, the data flow language is easy to parallelize. It's also relatively easy to use an FPGA to hard code the functions of the icons into hardware.
the problem with the language is it requires garbarge collection and is the memory management is not so good as implemented. It's not too speedy either. But as I said it may be that its parallel advantages and near bug free coding and easy debugging outweigh single cpu speen in applications.
Some drink at the fountain of knowledge. Others just gargle.
Is a stuffed frog I've got from my gf that sits on top of my monitor. When I need to ask something about a hard bug, I ask him first, and just by asking most of the time the problem gets solved.
It's interesting to note that a lot of those day-to-day bugs can be solved by simply straightening out your train of thought by posing a question in a manner that someone who doesn't know the system can understand.
Borland used to have a debug feature where you could actually follow pointers in structures like linked-lists and stuff, and get a graphical picture of what your data looked like. You had these little boxes that were connected with lines, and you could move them around, kind of like M$ Access's Query Builder tool. That was so awesome! It made it easy to see whether or not your data structure was messed up, or if it contained messed up data.
We use STL in M$ Visual C++ 6.0. When I need to look at an item in the middle of a vector, I have to iterate through it in the code. I don't think there's anyway to view an item in the middle of the list (you get the first item and the last item) without doing this.
BTW, if anyone knows of a way to do this, please fill me in!
dochood
Some sort of smart dump of every variable & call in your app at any point. (Offourse for a short period of time only to avoid overflowing your memory. For instance limited to the last 5 function calls)
This could allow you to replay a certain function with exact parameters as they were. I now often find myself repeating 5 minutes of clicking & typing to reproduce a certain function behavior of one line of code which *sometimes* crashes.
When will I end this grieving ? When will my future begin ?
My first (non-intern) programming job had a traceback buffer as part of in circuit emulation. As soon as you hit the problem you can look back at the last so many K of instructions that were executed and figure out what the heck happened and how some other developer or buggy compiler screwed up your perfect code :). So many hard problems were easier to solve that way because printf only works when you put it in the right spot and can really slow things down.
I used to complain about the tools we had then, but now I realize how rare it is that developers are lucky enough to have traceback buffers and even watchpoints (at least in the embedded world I program in) Most managers don't understand the value of spending 20K on a tool upfront because it could save you several weeks at the end of a project by fixing the hard bugs faster. You can just work 80 hours for them instead, thats free.
The best debugger I have ever used is Log4j. There is really no substitute for a good logging subsystem and grep. The chainsaw log viewer that is part of Log4j is also an excellent tool that can be used instead of grep.
I have also found that an interactive scripting language can be very handy. I use Jython for peeking into the state of Java objects and manually working with them. In my experience, this kind of manipulation can provide much better insight into the runtime behaviour of your code than an interactive debugger can. It can even be used to probe objects for which you do not have the code.
Of course, for non-Java development, there are usually analogs to these tools (syslog, perl, etc)
I'm working since the previous millenium (hehe, ca. 1999) on a complex, CGI-based application. Some day, I "invented" the "ultimate" printf() debugger for CGIs - a simple program that waits for input on a TCP socket and writes it to the screen or a telnet client on a second TCP port. The CGI to be debugged just opens a TCP connection and printf()s the messages into the TCP socket. All nicely wrapped in a small module, providing a single function named debug().
I never needed anything else for my job.
Back in those old days when Borland Pascal 7 was new and cool and I went to school, I was happy to have a debugger that could single-step into my Assembler code. But now, I have no more need for PEEK and POKE.
Denken hilft.
[mybox] dbx
(dbx)
help fix
fix (command)
Use `fix' to make changes to your program given. `fix' recompiles
modified source files and dynamically links the modified functions into
the application.
In Java:
System.println("MyVar = "+MyVar);
In C:
printf("MyVar is %d\n", MyVar);
In C++:
cout
In PHP
echo "MyVar is $MyVar <br>";
In Perl
print "MyVar is $MyVar\n";
Works better than any debugger I've ever used
HallmarkOrnaments.Com
I find myself routinely investigating problems with applications where I don't have immediate access to the source code, or where it's difficult to replicate the problem and we find that we have to correct it (restart, etc.) without getting an adequate opportunity to investigate.
I would love to be able to grab a snapshot of a process and identify exactly what it was doing. In some respects, this can be satisfied by getting a process to core dump and analyzing the core, but to date this has always been an annoying and time-consuming process, requiring source code to see anything useful.
Easy. ESP! I want it to know what I meant, and ignore what I said.
That's also how I'd improve today's compilers and run-time interpreters, by the way.
When the codebase reaches a certain size and complexity, you are going to be using a debugger, thats why this thread is taking place.
Often the data I'm working on is tough to just look at to see if it's right; being able to write something that would plug into the debugger to display some data would be cool.
For example, lets say I'm writing a scanner driver and I'm receiving buffers of data from the scanner. There's no way to know in the debugger if they look right or not - but if I could write a debugger plugin that could basically be given access to the entire address space the program is in with a target of "show me your data starting at this address if you can" it'd be awesome.
Same would be true for any data that isn't represented as a data structure or ASCII. I found often doing Win32 GDI work that I wanted to see what a particular HBITMAP looked like at a given point of the program's execution and the only way to do it was to blit it onto the desktop or something.
- Steve
perl -c myscript.pl
What's so special about that Eclipse thingy if it can't even do conditional breakpoints?
The only way of truely solving bugs is to know exactly whats going on in the code
This is the key. Anything that makes it easier to know what's going on in the code is good.
Modern debuggers like the one in Delphi (probably similar to J Builder's) make this fairly easy. You need the GUI interface so you're looking at the source all the time, command line debuggers obscure it. It needs to be absolutely easy to find out the state of any relevant variables. You need to be able to drop down into an assembly view (or some equivalent if you're in an interpreter) to see what code got generated at a low level.
The more *well-designed* stuff you add to the debugger, the better the opportunity for understanding the state of the program. Delphi doesn't have backward stepping; it would be great if it did, because it's often easy to detect that something has gone wrong, but hard to detect exactly when it happened. Conditional breakpoints are essential. Hardware breakpoints (which let the program run at full speed, but break when a particular memory location changes) are great.
You also want to be working in an environment where it's easy to add custom views of data structures, so that you'll see when things have gone wrong. Delphi (and probably Visual Basic, though I've never used it) are very good at that. If you've got a lot of numerical data, it's basically a one line addition to generate a graph of it, and one keypress and a second or two to wait to compile a new executable containing that addition.
You want tools like the various heap diagnostic utilities to be built in to the debugger, and you want system libraries to be written cleanly. It's easy to detect that you've got a memory leak if on exit your heap is always supposed to be completely empty; it's much harder if the run-time library leaves variable amounts of junk there, or if it's hard to determine what's there at all.
Knowledge about your program is good. Adding features that make it easier to see how your program runs makes debugging much easier.
Despite the slick graphical interfaces, nice thread stack traces and local variable browsers, I still make sure I have on hand plenty of notepads, graph paper, pens and pencils so I can try to build up a picture of what state the program is in and to help me play detective in pinpointing what is going wrong with my (or other peoples) programs. Do other developers have similar problems?
Several people have mentioned feature enhancements, many I would also like to see. However, your statement about stuck me as being a little deeper. Yes, we have the same problems. However, it is not the debugger it is the interface in general. Your desires are for the "paperless office." For years we heard about it, but it never came to fruition. In fact, it may never come. The problem with a User Interface is it presumes users think, and behave in the a similar fashion doing the same job. Ask two secretaries how they file paperwork for themselves. Look at the notes written by two experienced developers during a debugging session. Similar results? Certainly. Similar approaches? Possibly. Identical methods for getting there? Doubtful.
You need hand plenty of notepads, graph paper, pens and pencils because the task at hand requires you to keep track of abstract data. Why not screen prints, cut/paste of images, text, etc? Because the #2 pencil in your hand forces your to iterate you understanding (I am writing down X=2, then 3, then 4, then -32767 -- whoa!). In addition, you remove the "clutter" while also reducing the effort. Consider that you could cut/paste any sub area of the screen. X=2, now becomes X=2, cut, paste. X=3, cut, paste. X=-32767, cut, paste. X=2, 3, 4, 5, 6, 7 , 9, 37, -32767 looks very obvious. 37 records you must now relate together do not.
I have also come to believe that the device interface is part of the issue. It is easier (for me) to mentally connect the window on a monitor with the printed surface than it is two windows. Perhaps the solution is a 36 inch monitor where I can have multiple windows open, so I can see everything at once. But it would still suffer from relating data, which also includes looking away from the code. Perhaps avoiding the "deer in the headlights" visual lock.
WTF is this Ninnle shit anyway? Googling it seems to bring up only three websites, one of which has smething to do with baby talk. Is there Ninnle distro or what?
As a Web developer, time is on the line and almost everything I do is in a rapid development environment. That being said, debugging information is extremely important.
On the ASP.NET and Cold Fusion MX application servers, the debugging information provided by each is excellent and thorough. On CFMX, each error is specified by line on the template on which it occurs and provides a 'stack trace' (meaning a list of all the pages involved in generating that particular Web page), execution times for each template, and a complete list of all variables in all scopes. Complex variables, such as structures and arrays, are output along with all the rest in an easy-to-understand format.
The one thing that could be done better by every application system, IMHO, is a self-documetation feature. I would like to be able to look at the source code and see a breakdown of all variables on the page right away. This may sound a little simple and not really a debugging tool, but I look at it as preventive maintenence.
Real Programmers don't use symbolic debuggers. They use hex/octal crash dumps.
While it does make sense to be thoughtful and produce your best attempt at working code on the first try, clearly this is an imperfect process (for why, see a recent article in IEEE Software... software development is Knowledge Acquisition, known to be a rather imperfect activity). Thus, choosing not to use the most efficient techniques available means you choose to take more time than necessary. You really should not need to handicap yourself by eliminating a productive and useful tool to have the discipline to do the development of the software properly.
Peer review - without the peer:
http://www.sjbaker.org/humor/cardboard_dog.html
www.sjbaker.org
How many times I've had another developer come to me saying "Dammit! I've been through this a million times and I JUST CAN'T FIGURE OUT WHY IT'S NOT WORKING!!!"
I then take a quick scan through the code and see the problem in a minute or two.
The reverse situation has also happened.
If you don't want to repeat the past, stop living in it.
I have found Extreme Programming techniques to be very useful. I do much less debugging now, because I write unit tests as (or even before!) I write the methods. I use the JUnit framework for all the Java code that I develop.
I'm sure that debugging technology can and should be improved, but I think that better development methodology reduces the need for debugging.
ddd is, by far, the best debugger I've ever used. I used to hate visual debuggers, but ddd turned me around.
That being said, however, there is one improvement I'd like to see in all debuggers. That's a way to do memory checking. In other words, integrate Purify or Insure++ functionality into the debugger and have it break anytime there is a memory stomp. Memory problems are the biggest issue facing programmers of large, complex systems.
For those of you who say to write small objects and give them unit tests, or to rely on things like printf(), I suggest that you get a job in the real world. Complex systems are written by large groups of people. When you hit a problem, it may or may not be in your own code. It may or may not be because you're using an object incorrectly. You need a debugger to figure out where things are blowing up and why. Using printf() will work, but it's slow and requires multiple compile/link/test cycles. Not the best use of your time.
Debuggers are always doing what I say, not what I meant!
----------- Sig what?
I'd like to see a debugger that told me where memory had been allocated/deallocated.
Things like the last content of an object (if it has been deleted) and where that memory was allocated etc...
thank God the internet isn't a human right.
What about the code makes it bad? What is wrong with "playing" with your code until "it works" and the "edit and continue" school?
Hi, Slow as it has, purify/quantify type tools (that track and display memory leaks and time sinks, respectively) have gotten better. I had a Quantify-like ability in the OS I worked on in the 80s (PRIMOS), called PBHIST, for process something (block?) historesis. But, I find quantify very useful (except that it slows things down inordinately for really large systems) for point-optimizations. Purify integrated into an IDE has very high bug-finding value. Consistently running purify with a solid unit-testing suite is going to save you many headaches down the road. -J
I have found most tools adequate for more common development. The best suggestion is to actually create unit tests (if your language supports it) that help you isolate the problems. Once the test passes, you have solved the bug.
I know this sounds cliche. But don't many many developers hate debuggers with a passion? They can be extremely useful at times, but they can definitely get in the way. There has been at least 3-4 times in my career when a debugger was actually causing problems to happen! That ain't right.
Also, using a debugger often requires learning a new IDE. The best ones are usually integrated with some IDE that I otherwise hate. I understand why that would be the case, but I still hate it. I don't want to learn a new IDE!
--naked
Very popular slashdot journal for adul
I know the same could be achieved with lots of printfs,couts or System.err.println,( I use this technique myself, in conjunction with JAVAs logging API ) but those are a pain to add and remove from code, especially in JAVA.
Just my two cents.
IN SOVIET RUSSIA, the debugger bugs you!
Don't think the same old "integreated developement environment" but view the computer as one "integrated environment". Be able to write code once, test it once, implement it once and regardless of what programming language, shell script, or computer that you are on, be able to access it.
That is my current object within the Linux world.
But then again, MicroShit would be even less than "micro."
There's probably a technical term for the pair consisting of a position in the code and the path taken to get there. It's a bit like what a mathematician would call in a point in the universal cover.
Doesn't it make you feel good to know that our freedoms are protected by politicans, lawyers and journalists.
I know that this only applies to C/C++/Asm (maybe Pascal, too?), but hardware support is required for things like 'what lines alter what piece of code' or constant variable watching. These languages will either need to be fully emulated and interpreted in the design cycle (which has it's pros and cons), or the debugging facilities of modern CPU's need to be more robust than just 'fire off the breakpoint interrupt'. Not that amazing things haven't already been done with the tiny foundation that has been given (it's a miracle to me that things like gdb work), but I think we all need to find our local hardware geek and take them out to dinner and explain to him/her what it is we from them to make our jobs as software engineers easier and more effective.
As for interpreted and VM-based languages... this doesn't apply to you. You need to lean on your vendor for support.
So debugging code is easier for simpler, cleaner code. So KISS (Keep it simple and stupid) will be the best debugging tool, we will ever have.
How about instead of not using any debugging tools, you debug at write time?
For a lot of code, the compilier should be able to work out the pre and post conditions of a function, and then just check that when you call that function you don't violate them.
Also I'd like to be able to hover my mouse over a variable and see what range of values it could have. From here you can check that you never go outside the bounds of a variable, and so on.
Obviously you can never get it to work on all cases due to the halting problem, but it will work with a lot of code - and on confusing code you can manually add the special comments for the post and pre conditions - a good idea anyway for complex code.
Concerning the requests to be able to "reverse" the execution of a program ("Go back to the moment when this variable got set to null; what was the call stack like at the time? What was the value of local variable X (somewhere up the call stack) at the time? Now continue the dynamic execution of the program until the next time X changes..."): Such functionality is available in the RetroVue debugger for Java at http://www.visicomp.com/ (Gosling loves it, according to the quote on that page).
For all of my projects I have a carefully crafted debug library I use to encapsulate all of my objects.
Turn on debugging - and out pops the error in most instances. On the rare occaision when things get sticky, the debug code usually helps me zero in on the issue quickly.
You should also develop your own libraries of common routines and include them in every project. The more variables you elimenate, the less looking you need to do when a bug rears its ugly head.
How "stop modify variable" command works in dbx?
Intuition requires intelligence, and intelligence is something that computer programs do NOT have. One programmer's idea of intelligence is anothers roadblock that keeps him from getting the job done. Intuition would require the same amount of intelligence as a 'foreign language translating machine' that can translate based on the context of the conversation, and we are hundreds of years away from that. Frankly everytime I use a program that has some supposed intelligence built into it like MS Word, I end up getting extremely frustrated at the program, because the program prevents me from doing my job or I get lazy and stupid and let it do the work. Ever try to start a sentence with an uncapitalized word( just because you want to) or the grammar and spell checkers. Either way the program is very far from being intelligent and noone near capable of showing intuition. Maybe someday, but we will have to wait along time.
It would be nice to control multiple threads at once. It would be incredibly useful to test and debug critical sections and all.
I find I spend a LOT of my time debugging or working around bugs in the tools. Nothing is more aggrevating and frustrating than getting exactly where you need to get to find a bug in a program only to have the debugger itself crash with a SEGV. Between that, and the inability of many of these tools to work easily in the modern dynamic library and distributed computing environments, life is far more difficult than it should be using the existing model.
Thus, I want a debugger that absolutely does not crash. I want it to let me set breakpoints in any routine, even if it resides in a dynamically loaded library that is not currently/yet loaded. I want to be able to view ALL of my data in their abstract datatype form without having to look up their definitions and then manually guide the debugger through doing the job. And, I want a debugger that always honors my commands and does not lock up (which I find far too often with the GUIs layered on top of command line debuggers).
I am a long time member of ACM (since 1977) and have watched research into debugger technology over those years. I have seen attempts at dramatically different conceptual models for debugging, but none seem to have been successful. In fact, even most graphical IDEs appear to have been failures. I suspect this is all because ultimately things boil down to mapping program behavior to the code and verifying results are those that are expected for that code. There is little room for new or different models and abstractions so long as code remains the same. And, given the modern evolution of coding, it will be quite some time before the term "Visual" means something more than being part of the Microsoft Visual Studio suite while continuing to use good old text based software language(s).
This is actually one of the reasons I like the pair-based programming style set out in XP. Admittedly it is not really supposed to be for this sort of thing, but it is a really nice benefit
How come no one mentioned it? An ability to write debugger scripts helps immensely. In my environment at least, that is.
I just need the "why" command..
=)
A good debugger/disassembler is invaluable in finding obscure bugs. No amount of knowledge of your code and its structure can help you if a system call mangled a stack in a subtle way, especially with cumulative effects of buggy functions that have very very subtle bugs. Unless you are writting embedded code or something that doesn't rely on other code (an os, libs, etc.) you will never have a total view of what is going on. Debugging tools can help pinpoint generally where trouble is, and then it is up to the programmer and his detailed knowledge of the code to figure out what exactly is being affected and by what.
There is no right/wrong answer because "debugging" is such a vague term as well. Use all the tools available to you, and arrogance is not one of those. Nobody has perfect understanding of the internal intricacies of software running on top of an operating system running on top of a cpu.
The best way to beat a bug is to be knowledgable enough to use the right tool, at the right time, to find the correct cause of trouble. That could be anything from a cable tester, to a disassembler, to a coffee break, to another human being.
With lots of firepower.
Its eyes should be telescopes! No, periscopes! No, microscopes!
It should be full of surprises.
It should never stop dancing.
It should need accessories.
You have to use a whole range of techniques to get reliable code. A debugger is really only the last-ditch attempt when you really cannot figure out what has gone wrong. The main reason bugs can be hard to spot are when the error does not lie at the point of failure. To combat this, you have to have a robust testing suite so that errors are spotted early. You also need to litter your code with assertions to make sure your program has not failed long before the bug becomes apparent.
Timeline of watches. I.E. I want the debugger to log any changes in these variables over the life of the program. Draw it nice and pretty so I can see the order in which the changes are happening. but other then that.. I can't think of much else a debugger can do without some more hooks from the language/runtime... Line numners, Assertions, stack traces (with method names and stuff)... are all basic things that really make debugging easier.. but the underying language/runtime had to support them before the debugger could invent nifty features. So, what other meta information could we add to our applications to allow the debuggers some new features? I guess I didn't come up with an answer.. just another question.. that I don't know the answer too.. Maybe it would help if I used a debugger...:)
The hardest thing I've ever had to chase down were race conditions.
Race conditions don't act the way you'd think they would. If two threads both try to read a variable, you wouldn't necessarily think there'd be a problem, much less a problem that causes your program to suddenly decide to corrupt your hard drive and crash your program. And there's no really effective way to find out where the crash happened, because it happens at random, when you don't expect it.
Even printf()'s fail you here.
The only way to find a race condition is to hand-inspect code, and make sure every shared variable is protected by mutual exclusion.
If I ever got back into grad school, I could probably dedicate an entire career to solving just this one problem.
I think the real problem, though, is not that there's a lack of good debugging tools, but rather that the really good debugging tools are rare, and the more common ones may have power but are difficult to use. And digging even deeper than that, the real problem is that people tend not to use languages that will enforce programmer discipline and help to prevent programmer errors from getting into the software in the first place.
Visual studio 5 used to let you do this. You gave it an address and a range and if any memory contents changed in that range a break would occur. This was extremely useful when you had an errant memory write elsewhere in the program such as writing off the end of a string, etc.
This is different than watching a variable because you can't watch most variables all the time, only when you are in their section of code.
I was very disappointed to find that Visual Studio 6 stopped supporting this. You could give it an address, but it figured out what symbol (variable)
the address was associated with and ended up doing an ordinary variable watch on that (and when code was no longer in the class or code module, the watch was no longer looked at, as mentioned above)
Does anyone know if MS ever fixed this in later releases? (the last time I checked was back in 2000)
I've always wanted the ability to set a conditional breakpoint on a variable. Let me explain: Have you ever had an issue where a variable was changing and you didn't know what line of code was changing it? Well, that's the kind of breakpoint I would want. Set a breakpoint on: myvariable whenever it changes, and zip to the line of code that changed it. Take this one step further and you could set a breakpoint to go off whenever the variable in question reaches a certain value.
DISCLAIMER: This post was not checked for speling and grammar- if you complain- you're a whiner
Valgrind. It's the first thing you should use when you've detected a bug. If it's a memory related bug, nine times out of ten, it will find it immediately, as well as several potential bugs you didn't even know about.
Purify, an expensive, proprietary piece of commercial sofware, has got to be the most unbelievably timesaving debugging software out there.
While not perfect, it's a bloody godsend, because it detects (at runtime, usually when it happens, and not long afterwards, like program termination):
It basically helps you quickly track down the really nasty bugs. Instead of spending days pulling your hair out, you can nail the bugs in minutes to hours. It does cause your program to run 3-10X slower, though.
Yes, there are other, open-source alternatives that do some of the above, but none do everything, and many have problems. The closest things are the various debugging malloc()s, but they're useless for tracking down the nasty uninitialized variables (or for showing you the exact line of code that trashed the malloc()'d memory). One of the really nice things about Purify is that Purify works at the object file (.o, .a, .so, .lib, .obj, .dll, etc.) level and does not need access to source code (purify is generally a link-time option). You can run purify on other proprietary code for which you have no source code (very nice for seeing if the bug is caused by your code or someone else's).
It exist for both Unix and Windows. I'm pretty sure that it exists for Linux, too.
It also works with most (all?) debuggers, including gdb.
It's good. It's really good (even though it's proprietary). If you develop commercial software, and your competitors use it and you don't, you're at a serious disadvantage. It's that good.
(And, no, I don't work for Rational (or IBM). I'm just a very happy user.)
These tools are much less important than, e.g. version control, which should be standard component of every programming environment.
Modern debuggers are feature rich and IMHO don't need any improvement (perhaps some sort of usage control will help - to make one think twice before launching debugger).
'nuff said
Trolls lurk everywhere. Mod them down.
It's not that the debuggers need more features. It's that the design of the languages shouldn't require it.
For example, changing code while it's running. I heard Java is adding this for 1.4 or 1.5. Makes debugging easier, right? I could do this in Smalltalk or Common Lisp 10 years ago.
Add a method to a class? Trivial in ST or CL. In Java or C++, quit, recompile, run again. Type a line of code and see the result? Again, trivial in ST or CL. In Java you can sort of do it with an almost-Java called "BeanShell". And on and on.
If Smalltalk or Lisp had half the vendor support Java does today, I'd switch in a heartbeat.
Well, i am one of the cheesy devlopers that always use IDE's, i used Borland's CBuilder, Kylix, MSVC, and i havent met any major debugging problems except for a few bugs(i mean i had problems but i just handled them). Currently i am using Qt, and i have to admit, debuggin here is not easy, so i agree with u, WE NEED TO DEBUG.
The lunatic is in my head
But I only use debuggers for two purposes.
Purpose 1. Segmentation Fault (core dumped). Uhm, now where did that happen? Whip out gdb, find the line that generated SIGSEGV, and it's usually obvious how it happened. If not, I have it print out a stack backtrace. If I really can't figure it out then, a 5 minute walk around the block and I'll have figured it out as soon as I sit back down.
When writing in high level languages, I'm finding that debuggers are wholly unnecessary. In fact, I can't remember the last time I spent more than 20 minutes trying to track down a bug. *shrug*
It'd be nice if debuggers solved my problems automatically, but I'm really finding that I don't need them. I might even go so far as saying use of debuggers encourages dependency on debuggers, which in turn discourages thinking about the program itself. Not saying that EVERYONE does this, just that some of the best work gets done remarkably well even without debuggers.
The Linux kernel, for example, was largely developed without the aid of a debugger, and the core developers seem to eschew them. Here's a good thread on why the developers don't want to include a debugger.
Purpose 2. On the other hand, debuggers are remarkably good at helping you break program code. With having almost no experience using gdb, I was able to break the license key check on Intel's C Compiler in about an hour. I was amazed at how easy it was to attach a debugger to the compiler and skip the subroutine that performed the license key check. With no debugging symbols to work with. Disassemblers rule. It took another 10 minutes to turn this into a script that could be distributed as a wrapper for icc (called xicc), so all you had to do was set CC=xicc in the Makefile.
Sure I could have used LD_PRELOAD so that time() always returned a date within the trial period, but breaking program code with a debugger is just so gosh darn fun.
(call stack, what have you). If a debugger won't give you a stack trace (optimized code excepted:), throw it out. I've found that fixing a null pointer error is often as simpile as running the program in gdb until it crashes and then reading the results of backtrace. function name, parameters, source file and line nummber: (almost) everything you need to find out how that null got passed to your function.
Bill - aka taniwha
--
Leave others their otherness. -- Aratak
People fail to understand the purpose of VB far too often. VB is great for writing small apps.
Every big app starts out a small app.
("A program of a million lines starts with a single character.")
Over the years I had used many debuggers and always found I spent huge amounts of time on the process for very little reward.
Then I started using an inline trace system in my code. Simply put, I can output any text I like, a la printf anywhere in my program. All subroutine entry and exit points are covered by trace statements and critical branches and variables are traced. Each trace statement has a level associated with it so that the trace can show just high level execution detail or low-level detail on request.
All trace statements are output to a file if trace is turned on. The size of the file can be controlled, new files created every x megabytes, or they can even be made to wrap once a certain size is reached.
In the end, the trace statements are almost like 'live comments' that clearly show what the code is doing and why. If trace is not enabled, the overhead of the trace system is negligible. If that's a problem then a compile-time switch removes trace completely. I can even turn trace on or off and change it's level on a running process.
Since using this system I've never needed a debugger. When something goes wrong it is so simple to get the trace file and source code and follow what happened. For catching those bugs that happen once in a million executions, it is completely indispensible.
Sure, you need some discipline to write good trace in the code, but then again you need that discipline to write good code anyway.
Anyone else used a similar kind of system? My experience here is C code on UNIX systems. It might be harder to implement this in other languages or operating systems.
The inadequacies of debugging (not just the dubuggers themselves) as a method of ensuring quality is why methodologies like agile programming and extreme programming are garnering so much interest from developers. It's also why there has been an explosion of tools that can help with the creation of good software with fewer bugs, easier maintenance and a better chance of actually solving user problems. In the Java world, there is junit, mockobjects and log4J , that can all be used with ant so that tests can be automatically run with every build and source control systems can be automatically updated. One approach is the Naked Objects framework, which is a combinination of a design methodology and tools in one package that has advantages like the easy rapid prototyping and automatic user story docuemtation.
For example if you were using the Naked Objects framework to create a system, you might take the following approach (simplified here for posting):
Notice that approaches like this emphasize getting the design right and doing constant testing to ensure that the code that is delivered actually does the job that is expected of it. Debugging is rarely required when such methodologies are used, though profiling can be of some use.
Signatures are a waste of bandwi (buffering...)
While knowledge of a debugger is useful, it is only a part of the debugging arsenal. You can't beat the wisdom gained by experience. Some people are better at finding bugs than others. Some people have a broader knowledge of the interactions of various layers of software than others. The more bugs one finds and fixes, the better one gets at finding and fixing them. But move from one environment to another, and only the thought process is portable--you need to re-learn the context (which gets easier the more contexts you've worked in). And sometimes that environment doesn't have the debugger you're most familiar with. So again, the tool itself is devalued, and the ability to "debug outside the box" is emphasised. Sometimes you can't put a debugger on a system (live telephone switch); sometimes you can use a debugger but can't put a debuggable image on (same example--how's your hex and 68x00 assembler?). In short, a better tool isn't going to make debugging easier. It may shorten the time to identify the problem area, but it doesn't make the process of removing the bug easier, especially in huge systems with many interacting layers and heterogeneous nodes. That being said, I use stack traces, breakpoints, variable/parameter dumps, and registers when I can get them--and that's about it. The other features don't provide value to me (my opinion, but I'll share without imposing it). Design for debuggability--somebody will feed your software something that's out of spec. Controllable tracing is useful here, but put the control flags in a piece of shared memory that a utility can toggle on and off, because you can't modify environment variables for a running process outside that process. And if your execution environment is guaranteed to have a debugging environment available, master the debugger if you can, but make sure it doesn't master you so you can't debug without it. The best debugging toolset is, in order of importance, your mind, the source code, the occasional invitation to others to look at the code with you, a whiteboard or notebook, and a room free of distractions. Surface for air and refreshment every 45 minutes or so, and food every few hours (there's a reason the Jargon File has an entry for "rotary debugger"). Debugging software will inform this process, but feature-rich debuggers will not speed it up much.
The Seventh Rule: Take others more seriously than yourself, particularly when you are leading them.
I've been developing software professionally for over 10 years and I can count the number of time I've used a debugger on my fingers.
I've programmed in c, Objective-C, Java, and a little in C++. I've worked in healthcare, oil and gas, high tech, and most recently the financial field. In all cases I have found that I can track down my bugs by using my brains and sometimes inline print statements (yes, I admit it). I spend approximately 1/10 of my total development time doing debugging work as opposed to design or coding.
Debuggers are too big a context switch. They don't act like part of the IDE. The best I have ever seen is the debugger in Visual Age (by IBM). It allows some pretty amazing things: you can roll back the stack and continue executing, and you can change any code dynamically while debuggin (the debugger figures out how much of the stack needs to be rolled back to allow for the changes). It also has all the usual stuff like value inspectors, conditional breakpoints, etc.
The one thing I would really like is to have a more sophisticated watch system that allows me to use the IDE (not the debugger) to insert development-time only code. This would allow me to put in such things as print statements that would not be part of the "real" source code, but rather just part of my project. It would also allow logging, performance measurment, etc. to be done at development time. Note: I don't want to context switch into a debugger to do this!!!!
Helping with organizational effectiveness is our job.
Even front end tools are little help. DDD is much better than the cli but it still suffers the same performance faults as GDB and introduces some fun issues of its own. Even a 'commercial' tool such as Project Builder on Mac OS X groans to a halt with GDB running underneath and has some very odd concepts concerning when breakpoints are hit or not.
All this would be understandable if Win32 were the same but it isn't. Debugging on Win32 is a snap - just in time debugging, compile in time debugging, a debugger that works, integration with the editor and more. It is sad to say that if asked and irrespective of open / closed source issues, which OS were the better for development I would say Windows. In fact, if I'm faced with a bug in Mozilla, I'd rather fire up Windows and replicate the problem there than wade through the shit that GDB throws in my face.
Die GDB! Linux really needs a decent debugger and all the mod cons that Windows developers have benefited from in the past decade.
Recently I was given some Java code and asked to port it to C++. At the time, my knowledge of Java was pretty much at the "Where is the bathroom, please?" level. In particular, I could see where the reflection package was being used, but not how the program went from one particular bit of client code to another. I loaded the code into the debugger, started the program, set a few breakpoints at the really puzzling parts, and ran through it a few times. At that point, the student achieved enlightenment.
... and become more likely to run the darned thing and see what it really does. Sometimes, in this job, inspection is theory, and debugging and testing are experimentation.
As I've gotten more skilled at software development, I've become better able to read a bunch of code and analyze it
An MIT animal physiologist is said to have told his students, "The animal is always right. When in doubt, ask the animal." Ask the code; the code is always right. (It may be right in knowing what the bug is, but sometimes that's what you need to ask.)
P.S.: I've learned more Java since then. Running some programs through its debugger was one good way to help learn it.
Stupid job ads, weird spam, occasional insight at
Debuggers causing errors is a mojor problem that thankfully I havn't run into yet. Unfortunatly, I get the opposite, the debugger fixes the problem. First you set a break point and find your variable empty (confirming the problem), then you add a watch to the variable and find out that it never empties (confirming that it's going to be one of those days). The only way I've found to get around this is to create a dummy varaible and set it equal to the variable that seems to lose it's value. The down side to this is it looks like outragously poor code (and is), and reflects bad on the developer and the company. I'm terified of a coustomer looking through our code someday and having to explain it. What do you say to that? "Hehe, well... I was smokin sumthin goood man..."
There's a reason the experienced coders use printfs and couts for debugging, they always work.
"Debuggers are useful, but I see too many freshouts using them exclusively to fix code, rather than just looking at the code to analyze the design."
What I would like to see is debuggers that fit better into the idea that software creation is a process.
Look at all the rich information lying around, just being thrown away, or underutilized, all along the process, that could be fed further up/down the pipe that could make things easier.
Imagine debuggers that have a better grasp on your code than you, because it peeked at the information in the planning phase.
Imagine dcumentation tools that have access to all steps, and can pull it all together, and help during the debugging phase answering "what's the difference between what I meant, and what I am getting?"
Imagine planning tools that can pull in outside information from the problem domain that your about to work on, and help in the integration/exclusion process.
Imagine internationalization tools that can pinpoint problem areas when doing a cross-culture application, as well as help in the translation process.
Imagine profilers that at least have a clue while looking further up the chain, and helping better during the "make it better" part. "What would you like to optimize today?"
Note to all that we wish our "aids" to be all inclusive in helping us solve our problems, and will settle for tools that help us to be on time, under budget, and we all can go home on a "clock cycle".
Turbo Pascal used to have a Step Backwards that was terribly handy. It was so nice to walk forwards and backwards through a tricky bit of code trying different scenarios. I've never seen it anywhere else. -DJ
If you don't have another programmer handy, try the practice of Rubber Ducking.
This is where when you are completely stuck, you take a little break. Then you come back, pull a rubber duck out of your drawer, and put it on your desk. Then you turn to it and say, "Rubber duck, here's my problem," and explain your troubles to it, just as you would to a fellow programmer.
About two thirds of the time I try this, I stop half way through and say, "Aha! That's the problem!" And even if the solution doesn't occur to me, the process of explaining the problem makes me go over it in an orderly way, so that I always think of new places to look.
Most of this discussion seems to be about interactive debugging tools, but as an individual concerned with mission critical telecommunications software where an outage can take out customer private networks, I tend to find less need for interactive debugging, and greater need for post-mortem diagnostic analysis that results from the following:
- faults generated in house system / integration testing
- faults generated in house automated unit / component testing
- faults generated in house automated system / scalability / performance testing
I need to isolate sometimes highly obscure run-time failures and discover what went wrong, then resolve the issue, which I do with:
- high levels of run-time instrumentation using (a) method / object / runtime c++ trace style classes, (b) trace back mechanisms for exception handling and, (c) assertion handling and (d) run-time verification mechanisms; all of which generate output to debug logs (sometimes when returned to support, these logs are multi-gigabyte in size, fortunately our development workstations are very high spec)
- post-mortem analysis scripts to interpret the contents of debug logs and look for faults, inconsistencies and other issues
- application level mechanisms to allow testing, deployment and other experts to enable run-time debug instrumentation (if it were enabled all the time, it would constitute considerable performance loss) sometimes at the direction of developers or deployment / field support personnel, and sometimes these personnel don't have access to machines where the components are installed (because the components are distributed CORBA components, and these personnel have access to host / user interfaces, but not to components in a silo in another country)
The problem is that we've had to design all of this from scratch: (a) general purpose c++ based debugging / tracing modules with command line / run time configuration options, (b) tools to stimulate the debugging facilities to do things [set / change debug trace levels / activation tags / identifiers], (c) tools to capture / wrap up and return trace logs back to support, including capturing host information (processes, memory, installed modules, environment, configuration) and other debugging items (debug stack traces, core dumps) and version information (component version, etc), (d) tools to analyse / work with / process logs for developers, (e) work instructions / process / documentation to educate developers, deployment experts and others about the use of these facilities, (f) make sure that there's a balance between getting the right level of detail, yet avoiding gigabytes of detailed code / method level information
Typically, once I have a debug log returned to me (as I am developer), I need to look at what was going on, and try to reproduce the fault with a unit test case, then inspect the component for faults of a similar type, and correct those with appropriate unit tests as well, then verify regression test for the component, make changes to multiple development branches, and wait for the scheduling of scalability / system / automated testing to ensure no other significant side effects, then safely know that the next release will have corrections.
We shouldn't have had to develop all of this in house: there should be standards for this. Other companies that I have worked with have the same adhoc construction of debugging facilities - for these situations were you need to analysis a running system, or obtain post-mortem results.
Interative debugging dwindles in comparison: unless you are working with obscure hardware, or related sorts of embedded systems, I think that an excessive need to use interative debugging says more about the lack of design / defensive coding / other engineering approaches to reliability of the constructed software. Interative debugging consumes about 10% of my debugging efforts (not including time spend on unit / component / system test design).
What I'd like is the ability to display complex structures, such as GWorlds, HBITMAPs, etc. I do a lot of image processing, and just being able to look at the image I'm processing can instantly tell me I've got an off by one error. But trying to figure it out in code is not always so simple.
The other thing is to come up with a debugger that doesn't have any side effects with the rest of the OS. Unfortunately, that's probably not possible given what debugging is. But I can't tell you how many times a bug is hidden by or caused by the debugger. That's annoying!
At every job I've had in the last 3 years I've insisted on 2, preferably three monitors.
Monitor 1 always has the code open.
Monitor 2 has the Web browser for the CGI ( which is what I write ).
Monitor 3 has the interactive debugger running.
If you can't justify 3 monitors, you combine 2 and 3 on one monitor.
" the best way to build a skyscraper is not to use CAD programs at all, but a slide rule and pen'n'paper, which force you to think about what you're doing instead of making mistakes and 'correcting them later'."
Skunkworks
Opionion(MS Haters): Anti-MS sentiment and general eliteism feed the notion that MS produces mostly crap and VB is the biggest pile of it. Also, simply looking at the easy learning curve and the general "point 'n drool" nature of it makes it inferior. It propells the notion that "any idiot" and create software and that with VB in hand, most "idiots" do.
Fact (academic types): A little bit of exposure to origonal BASIC shows VB to be a sick mess on technical merits (or lack thereof). VB changed indexing (e.g. origional BASIC String functions are 1 indexed, newer MS VB fuctions are indexed from 0) and enables bad programming practices (global variables, defined GOTO for cryin' out loud). Those you may be able to forgive, but then there's what the die-hards point out: there is no Backus-Naur Form Grammar for the language, and no alternate definition for one to build an interpreter themselves. This speaks somewhat poorly of the language and it's "ilities" (portability, maintainability, etc.). It locks it into the "silly vendor tool" category and most self-respecing academic types refuse to touch it.
*** Sigs are a stupid waste of bandwidth.
It must be nice to be one of you folks who work on one of those projects where you can just use your brain to understand all the relationships among data structures and various pieces of code or where you can make sure that you only ever work on code where you can be sure that it's structured cleanly with nice small functions that can be tested individually.
Out here on the wild frontier we're stuck working on code that was written many many years ago by people who weren't quite so clever as the average slashdot poster. These people left behind badly structured code with inelegant data structures and comments that don't accurately describe how the code works. This code consists of several tens of thousands of lines in the component I'm directly involved with and several hundreds of thousands of lines in the larger project.
So while it sure would be swell if all the functions were small, the data structures elegant, the code tidy, and the comments accurate, that's just not the way it is for many of us.
And it pains me to say, but much of the debugging we do is done using printf() because most debuggers are such unredeemable sacks of $#!].
I do much of my debugging using msdev from VC++ v6, and I find it to be even less useful than the CodeView debugger that I used in 1987. There's a few things that are better but there are a lot of things that are worse. How can I get msdev v6 to show some of my variables in hex and some in decimal? Is this such an esoteric request that the developers at MS couldn't be expected to anticipate it?
The number of things that the MS debugger can't do that I could do in 1992 using IBM's VisualAge C++ debugger is even longer. Is this progress?
Ok, I've found that sometimes I discover an age-old program that I wish I'd known about for years.
In the hopes of finding another, what are the best debugging tools we have NOW?
I find that NuMega (Compuware)'s suite of debugging tools to be much better than anything else that I have used. BoundsChecker especially is an extremely useful tool for find bugs in C/C++ code.
With a traditional debugger finding memory leaks, overflows, and other errors that may not show symptoms imidately can be a lot of work.
I think that it is asinine to believe that such tools haven't improved the debugging process in the last 30 years.
Grrrrr... don't bother me, I'm thinking.
is to not ENBUG.
The revolution will NOT be televised.
Log4J is my debugger. 'cuz my webserver has no stinking GUI!
there's no place like ~
1) I loved how Java has compile-time enforcement of exception handling. That is, if some code you called threw an exception, you HAD to handle it or else it wouldn't compile. This drastically reduced debugging needs. This idea should be greatly expanded upon!
2) I would use debuggers more, but often I find that getting a project prepped for debugging takes far too long. It gets too hard to configure the debugger to handle hoards of files, libraries and other things. Or when developing games, you're in full screen mode, and the last thing you want to be doing is popping back and forth to windowed mode.
I agree that we need a new paradigm which gives programmers control but without the heavy GUI.
Does it hurt to hear them lying? Was this the only world you had?
If you've ever followed the popular system computer simulators known as emulators, you've likely seen savestates. It's effectively saving all the variables of a system en bulk, to be leaded back again later so another approach might be taken. They have been very useful to emulator developers who often need to return to an exact point where a virtual machine breaks down, without having to re-run to a certain point.
It would be nice if debuggers could automate the process of saving the state of functions (and everything they immediately touch), so you could go "back in time" rather than need to restart a program in order to return to a non-bugged state. On small programs, it would also be very convenient to be able to save the state of the entire program.
Possible extentions of this idea would be a breakpoint-like auto-savestate at a certain line, and a "step back" feature to be able to rollback one line.
Of course, there would be many possible complications involved in using savestates - but I believe the potential dangers are far outweighed by the opportunities for quicker and more comprehensive testing and code-observation.
Ryan Fenton
I find that people who use debuggers rely on them like a habit. A co-worker of mine would be lost without Totalview. For him, developing and testing software would not be complete without a debugger handy.
For me, I have given up using a debugger because its annoying to run and to use correctly. I used to use gdb through Emacs and the process became so time consuming. Now, I use a process of commenting and outputing. If the code is written correctly (appropriate return values, funciton usage, etc.), this can prove to be sufficient.
Both methods are laborious and time consuming, but are a matter of preference and what you are used to. Software development was never meant to be quick and easy...
100% Insightful
For example, if a variable has a wrong value, being able to click on it and the debugger tells me all the variable on which the incorrect value depends. I can then trace back and inspect the values of the contributing variables. Once all the contributing variables have the right values, I know a problem is 'downstream' of that point.
It would also be nice to be able to go the other way. Click on a variable and the debugger tells you which variables depend on that variable.
http://www.lambdacs.com/debugger/debugger.html
This guy gave a presentation on "Omniscient Debugging". Apparently the tool can state changes in program state (including those of multiple threads), starting and terminating at a specified times, so you can basically go forward and backwards across an event and analyze it. It seemed pretty nifty to be able to be able to "rewind" a bug event at will.
would be a good start -- including namespaces.
If you don't believe me, try a simple application with namespaces and you'll see a problem. Also, I've had numerous problems with gdb giving errors about "cant find some C++ RTI symbol" or some error like that, don't remember the exact error since I'm not at that computer atm.
For C, gdb is great, but C++ definetly needs some work and looking on the gdb lists will show you that I'm correct.
I can understand where you're coming from if you're talking about debugging non-VM and non-interpretive code. Even then, a lot of newer debuggers use methods which could handle most of these issues. 2) Where would this stack of previous values go? What if it's the control for a loop? A buffer variable that updates every second? Your compiler could compile in code save values as they are being changed, in an array of stacks somewhere. You could probably limit the stacks to only the last 10 values. 3) Same point, just makes the stack bigger. Should it cross reference all variables so you can see what that all were at that point? Pretty much... 6) So the debugger should be able to wrestle a process away from the processor without previously having linked into it, and then map memory locations to variables and procedures? That would be impressive. Impressive if your code was compiled to machine code. If it's been compile to bytecode and being JITed, then it shouldn't be so hard. The future is going towards JITing.
I used to work for a company called Saber, who later changed their name to Centerline. We produced a product called Saber-C (and later Saber-C++, and the products were renamed CodeCenter and ObjectCenter).
This product was a C/C++ superdebugger. It started out as a C interpreter developed at Harvard. Now, an interpretive environment allowed a lot of neat features: You could tell whether or not variables had been initialized at reference time, you had complete stack and context information, it was pretty easy to unload and reload code in source modules (dynamic reloading). You also got dynamic type checking, which caught errors in downcasting (for instance). And everyone's favorite, array bounds checking.
With this tool debugging C code often meant: Loading the code, running your test case, and seeing where the debugger complained. The first time you ran your code through it was a humbling experience ... almost all production code has serious (but normally benign) errors.
Unfortunately the tool didn't scale well because it took time to load the interpreted code into the debugger and the heap and runtime requirements of interpreters stressed machines of the time (this was when Sun3s were common, and 3/50s couldn't even have more than 4MB memory).
I think it was 1990 when we released version 3, whose big new feature was object code debugging (it's not really that easy to have object code debugging as well as interpretive code, although we could certainly have implemented it more easily than we did). We of course maintained the ability to dynamically reload code fragments, so you could do a "make", reload the affected modules, and be on your way in a few seconds. This sure beat the several minute wait you normally had with the linker and debugger restart. But what you lost was some of the runtime checks -- including most of what made the product interesting. Still, the ability to have superdebugger capabilities on some code and still scale to large programs was very valuable.
About a year, maybe two years later we got visited by the people who eventually started Purify. They had a neat approach where they'd get most of the benefit of our tool, but in object code, by disassembling the object code, adding extra code to perform checks, and putting it back together. This would give about 80% of the functionality of our debugger but with much lower runtime costs and work even if you didn't have source code.
We ended up re-implementing this functionality such that we had a Purify competitor (and getting sued, and losing, even though Sun later patented the same technique we used).[1] Integrating it into the debugger allowed you to fine-tune the debugging capability you wanted on a module-by-module basis. This was a superb tool.
Now, what are the raw capabilities that made this stuff really neat?
The tool also provided two additional interesting features. One was called "action points". Since we had a C interpreter in the product it was no big deal to allow you to type C code into it and run it at arbitrary times. We'd allow you to attach any code you wanted to any line in the program or to just type code at the debug prompt and it would run in the current scope. This was useful for things like adding print statements without recompiling, for instance, and for adding assertions, and many other things.
The other feature was a graphical heap inspector. All this did was display structures as tables of their internal values and allow traversal of references to other structures, which would be displayed (including links between the structures). This made the shape of data a LOT easier to determine.
Several people talked about adding reverse execution. That was actually done for Java by a tools company back in 1996 (maybe 1997). It didn't always work, but it was pretty neat. The problem is that the recording code was pretty expensive and there's a limit to people's patience and what they'll spend on hardware (although I grant that hardware is a lot less of an issue today than it was even in 1997, to say nothing of 1989). Anyway this feature is a lot less interesting if your debugger can find errors at the point they occur.
Anyway, back in 1995 when I started to work with Visual-C++ on a regular basis I was appalled by what Microsoft was calling a "state of the art" debugger. Feh! It was 1985 technology with a pretty face. It really has not improved much since then either, although they do at least have a pessimistic heap allocator now. With their ability to hook in with the compiler they could do a phenomenal job with heap allocation tracking and instrumentation of code with error checks but they don't bother (because, I suppose, they make their money even without it).
Now, using a language with runtime error checking built in - such as Java, C#, or Visual Basic, seriously undermines the amount of effort you have to put into the debugger. Still, I'd like to see a lot better heap debugging features built into compilers and runtime environments.
Hope this gives people some ideas, and that they lead to tools I can use.
[1] One thing that could be done to avoid the Purify patents would be to have the compiler emit the instrumentation. For the OSS world, where you always have the source code, that is eminently practical. Furthermore you can get all the benefits of an interpreter but at higher performance. A big problem with Purify's technology, and the technology we came up with, was that you're doing a lot of heuristics during code inspection. It's easy to miss code or misinterpret code, and of course the code inspector is VERY architecture and compiler dependent. What I would like to see is a gcc/glibc/gdb combination where the compiler, libraries, and debugger all worked together. That wasn't possible back when the vendor controlled the compiler and you didn't have access to library source. Today it is, at least for the OSS world.
jim frost
jimf@frostbytes.com
This is more of an IDE thing than a debugger thing, but I'd really like to have an automated way of finding all the call sites that access a particular class or struct member.
... };
e.g. if I have
struct foo { int count;
I want to see all lines of code that access the 'count' member of struct foo. (WITHOUT showing all other occurrences of the string 'count' like a simple grep would).
Bonus points if the feature can track pointer aliasing - e.g. in the example above, *((int*)&foo) should also count as a hit... Or if I have an array 'int arr[]' and I want to see all access to arr[3], including *(arr+3) and arr[i] where i could equal 3.
One of Borland's more excellent products...
It did have backstepping, but there are limits to what you can backstep over. If you do any IO (filesystem, ports, etc...) backstepping really doesn't make a whole lot of sense. For pure computation, however, it rocked.
With an app that is multi-threaded, the semantics of backstepping might get a bit dicey. Might be a nice PHD research area, though.
-xbytor
I mainly use PHP for my development, but when it comes to client side applications I use Delphi / Kylix. For your basic simple things, it works quite well and has some nice debugging and error reporting. However, when doing things like database working using the BDE, its a nightmare. Most of the time the errors don't point to anything to help debug it. The errors are sometimes so general, it could mean someone forgot to put the toliet seat down.
I have found that many developers (of the debuggers or IDEs) don't spend enough time creating error messages for all sorts of common problems.
They have gotten 10 times better in recent years. I personally *hate* most C / C++ IDEs becuase the application just segfaults, or what not instead of saying what the hell happened. I am a poor C / C++ programmer, so it doesn't help me move any futher into it.
until (succeed) try { again(); }
To a certain extent programs like purify and bounds checker do automatic program debugging. BC will check for all kinds of runtime errors. Coupled with tight coding standards enforced by a lint like tool of your choosing a _LOT_ of bugs will be easily isolated automatically. When you combine these tools with a code coverage utility, a decent set of unit tests, a test utilty that can fail system and library calls you will discover a the bug count in released code will go down to nearly 0. Finding these bugs in developement is a lot easier that trying to do it with a core dump from the customers site. Take it from me I've worked for companies that released software where bugs that cause crashes, lost data etc were simply not acceptable.
People complaining about the debuggers themselves missing functionality are complaining because their code is either to poor to isolate the bug when it happens (causing it to propigate into areas where the bugs arn't ovious), or they simply arn't using all the tools avialable to them. Don't underestimate how useful enforced coding guidelines can be for writing bugfree code. There are whole classes of bugs that can be caught by a lint, but will result in hours of debugging. Variables that never get initialized are the perfect example.
I used to use a debugger to walk through my code as a sanity check that it was doing what I expected.
Recently I've been in an environment where the IDE was not integrated with the app server, so dubgging meant creating log infomation.
With server side programming and as systems become more complex, debugging on a single thread level is not important and in some ways irrelevent.
To find a problem I've had to grep through huge amounts of logging information.
Maybe that's where some tools development should be headed, to searching and organizing logging output.
is for a debugger that can do a good job in simulating multithreaded operation. If a debugger could:
1. Break all threads in one or more processes
2. Simulate timeslice execution of all threads as the user steps through
That would be very good. Many of you probably noticed that debuggers don't do a very good job of this, and sometimes threads can either behave too well or too poorly.
Another nice feature would be the ability to have complete control over what threads to starve and what threads to execute. This would make testing of critical section code much easier by giving us the ability to simulate worst case scenarios in matters of concurrency.
Finally, I'd like to have more extensible debuggers so I can create my own variable watch plugins that depict things more graphically than a simple watch list.
Hate to break it to you, but if y^1/2 is implemented as a true function with a single return value, it is not the reverse of x^2.
Say you have y = 9. Was the x that was squared to produce that 3, or was it -3?
Similarly with sin. You know that y received the value of 0 after assignment from sin(x). But was x 0, pi, 2*pi, 3*pi, etc.?
That's just the theoretical problem; there's a bigger practical one involving floating point values. When an operation or cast causes precision loss there's no way to get that precision back. Let's say y is a float and you shift it to the right by 3 bits. Those 3 LSbs are gone forever, and there's no operation that can reverse that unless you log the value of every variable that undergoes an irreversible change.
All's true that is mistrusted
Something VB6 has done for years is that you can modify, add or remove code at will while executing the apps.
This was really great to test code without restarting the whole thing. I have yet to see that in another debugger.
Sad thing is, VB.Net doesn't this feature anymore.
Intelligence shared is intelligence squared.
http://www.lambdacs.com/debugger/debugger.html
An interesting contrast to this is in embedded development. I can't think of a single embedded designer who doesn't consider tools, esp. debugging tools, when choosing a processor for a project. No, they're not sexy, but they can make or break a project.
The Ocaml debugger (see the Caml site) has the ability to travel back in time.
Also, type inference of the Ocaml language find a lot of bugs at compile time.
I believe that higher level programming languages will lower the need of debuggers.
At last, as other comments show, many programs (e.g. servers, CGIs, ....) are difficult to debug with a debugger.
I don't know about you, but lumping the rest of us who use debugger in with the heap of "cherry picking" amateurs, sounds REALLY arrogant.
Firstly, I'm like you, in that usually I know where my problems are, and I don't need to do a step-by-step trace to find my problems. BUT sometimes I do, because sometimes we ALL overlook something. Secondly, I work with a lot of other people's code. I don't have the luxury knowing exactly what's going on in the code, and debuggers help me fix other people's bugs a lot faster than speculating.
I'm just sick of these one-size-fits all opinions. Just because some people use these features as a crutch, doesn't mean the rest of us having found real value. More features do not cause undiciplined programmers. They were undiciplined before the features got to them. There will always be undiciplined programmers.
You're not going to change them by taking away thier features.
NOTE: The bold is used to highlight points, it's not for yelling.
http://www.ocsystems.com/rootcause_white_paper.htm l
It does everything you asked for except reverse-execution but since it lets you re-execute what happened right before the problem it accomplishes the goal you wanted.
things have changed drastically for us in the last decade or so. we have ICEs and hardward debuggers with many times limited functionality, so we still end up using scopes, logic analyzers, and utilizing the free IO ports wiht the help of some LEDs.
however when we are lucky we get decent debug symbols and more than one breakpoint to use (darn ROM debugging). i would have to say you guys working on the upper layers have it easy. i would kill to be able to see the amount of information you guys have for board bring up.
icis machine
A well-known need in academia: proven correctness.
If the precondition is satisfied, the code fragment is guaranteed to result in a state that satisfies the postcondition.
if Apre is taken to Apost by A, Bpre to Bpost by B, and Bpre is implied by Apost, then AB takes Apre to Bpost.
When a proof of correctness for a code fragment fails, some set of initial states will not be guaranteed to work. By examining that subset of initial states which aren't guaranteed to work, one can generate test cases and determine whether the prover needs more axioms or else that the program is actually incorrect.
Proving correctness is often difficult, but this is largely due to the grunt work involved (which is another source for human error). One needs good tools to minimize the human effort.
Sure, your program-proving system has to be correct itself, or else you get nasty bugs, but that same situation doesn't keep us from using compilers. And this doesn't eliminate all correctness problems, as specifications virtually never come with enough detail to support this process without programmer effort, but it would certainly be useful to have better code-proving systems.
And if anyone knows of available systems that actually provide these tools, by all means let us know!
I would kick someone in the knees for an x86/Win32 disassembler that's as intuitive and easy to use as PS2Dis is for Playstation 2 MIPS code.
I'd been using that one for awhile (finding hidden bits in games I like), and I decided to check out the same kind of software for x86 disassembly. I felt like I was back in 1992 using DOS tools. Essentially all of the interfaces seem to be text-only, and there's none of the "click on an address and modify the code" functionality of PS2Dis, or the ease of navigation.
Since I'm only doing this for fun, it's just an irritation, but I imagine it would be very frustrating for a full developer.
"...always new atoms but always doing the same dance, remembering what the dance was yesterday." -Richard Feynman
I think the biggest advance in debugging would be teaching people to use them.
I know a lot of programmers, but I think I'm the only one I know that actually uses a debugger to find problems. I haven't personally seen any University courses on debugging techniques or tools.
I think it's an essential skill (like typing) that makes programmers *so* much more productive.
-me
Love many, trust a few, do harm to none.
1) A facility for examining variables used as bitflags. MSVC++ will let me see a variable in every way except binary. I'm not geeky enough to know what bits are set by looking at a hex or octal value. Not yet, anyway.
2) The ability to backtrack the flow of execution. Not just see a call stack, but actually move backwards and repeat certain steps to see over and over again how they affect state.
3) Better GUI debugging all around. The mechanism by which windows or dialogs update is designed to be fast, sure, but it often prevents the developer from seeing how the GUI changes or responds over time. GUI developers need a GUI debugger. "Magic Lenses" are a good step in this direction.
4) Better fault/bug prediction. If people can diagnose future problems by examining the code, the computer should be able to, too.
5) Statistical analysis detailing which bugs a developer (a student, in particular) cause/encounter most often.
6) More debuggers that suggest solutions to problems.
7) More general breakpoint descriptions. I'd like to be able to tell the debugger to break whenever any variable in the system equals a certain value.
in context to enterprise/web development its common to develop in several languages (usually at each of the different tiers e.g. HTML/Javascript on client, Java/C++/etc on Business tier, some flavour of SQL as a backend).
In some cases it is useful to be able to debug across tiers...e.g. interatively debug starting from scripting in the client, when a call to the server is made, trace the call to the component in the middle tier, debug there, and then further trace into DB stored procs if needed.
Visual Studio has had these sorts of features for a while--granted they are often a bitch to setup (and as a result somewhat less than trustworthy)...but when you do have it configured correctly it works quite well and has saved me a lot of time (now if they could address the "bitch to setup" part)
I'm a bit MS centric in my dev experience but some that I like are:
Edit and Continue in VB:
find a small stupid error while debugging? fix it right away and continue...this can generally only be done with very simple errors (e.g. change a value assignment to a variable)...but it saves the time of stopping and restarting a debug session to fix a dumb error preventing you from continuing.
they implemented this in VC6 as well..don't know how well it worked, because its the sort of thing that only works well if it is unobtrusive--sort of like code complete drop downs...great in VB (cause its lightening fast), pain in the ass in VC++ (and many other IDEs--cause it slows your whole machine down and just gets in the way).
some ideas that I think'd be useful but have never encountered:
Simple refactoring while debugging (e.g. find a badly named variable while debugging?, rename it on the spot (and have all other reference renamed) and continue debugging...imagine in some languages this'd be quite difficult to implement but in an interpreted scripting language probably doable)
Mark a function/module/library/component as "black box" so that the debugger knows NOT to step into any code in that portion of code. This would speed up pinpointing of errors where you have code linked to 3rd party libraries (e.g. writing C++ code and then ending up in nasty MFC code)...the errors could be in those libraries...but if you're pretty sure its your own code (cause its just your first cut on it) then this could save some time....you should of course be able to mark it "white box" just as easily--having this feature sort of extends the idea of "information hiding" to debugging by giving the dev the ability to focus on the specific area he/she is interested in
--this sort of feature could be expecially useful in code walkthrough exercises where you want to focus the code walkthrough on only specific parts of the code and ignore previously examined code/3rd party code you're not interested in.
that's my 2c
that's my 2c.
With a suite of unit tests, I rarely have to invoke the debugger. If you need pen and paper to hunt down the problem, you probably are missing unit tests at the appropriate boundaries. They keep the problem small enough that you can tackle it with regular debuggers.
Most of the responses are missing the point, I think. Step outside the box for a moment...
When you write software, you have an intended interpretation, namely, what you intend the program to do based on what you meant to write. The compiler, on the other hand, has its own interpretation of your program, based on what you actually wrote. Debugging is the process of finding discrepancies between those two interpretations.
Understanding this reveals what directions debugging tools should go. Current tools put the programmer in the driving seat, trying to understand how the system has interpreted their program. The next generation will put the system in the driving seat, asking the programmer what they meant that operation should do. Like with a human teddy bear, the act of explaining it to the system might even clarify things enough in the programmer's mind that the problem may become obvious. Or, we may end up in a kind of "pair debugging" situation where the system becomes a code reviewer.
sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
Ok, lots of responses along the lines of "Real Men Don't Debug" to this post, but whilst I'm sure all /. developers write fantastic code with no hard to track down bugs, in my experience you can spend a lot of time tracking down other peoples bugs! - you don't always get to work on nice clean systems from scratch.
Another reason I think it is important to focus on debugging tools is that, despite the name, they are not always used to debug! One of the major uses of a debugger is to understand the dynamic behaviour of a program.
Whilst not so big an issue in the current climate, there was a time not so long ago where companies had a very high turnover of developers and it was very common to start work on a project where the previous developers that did the bulk of the work were no longer employed there. Often UML and design documents were no-existant or well out of date with the actual source code, so the best of figuring out just how the system worked was to load it up into a debugger and see what it did.
Before I get replies pointing out that a good code review will reveal the workings of the program, I'll point out that often the dynamic behaviour of a program (and this where the need for good debuggers comes in) - how it responds to various inputs - can often be hard to assertain in non-trivial systems. All programs are essentially Turing State Machines and if it were always possible to work out how a program would run from it's source code there wouldn't be such a thing as the Halting State Problem would there?
A quick example to finish off this post and perhaps generate some more discussion on debuggers (or perhaps to use a better term, Program Inspectors/Visualisers) - design and code reviews are not everything. A simple example is a Binary Tree used for sorting input data. The UML diagram is very simple, the algorithm straightforward. According to the design and code review it should deliver O(log n) performance to find a given item. But as any student of computer science will point out, if you input an already sorted dataset into a binary tree structure you end up with a list with performance degraded to O(n). It's a trivial example, but it does highlight the need for understanding how programs respond to different inputs at runtime - something that better debugging tools would help with.
So, now imagine you have inherited some monolithic monster of an undocumented system. Nobody knows how it works or was put together. There are two dozen outstanding bug requests that you need to fix..... just what sort of debugging tool would you be praying for at this stage??
The effort has gone into improving the languages and techniques so debuggers aren't needed as much. For example, adding unit tests and Design by Contract (see D) greatly reduces the number of bugs for which a debugger might be needed.
I've never met a Java debugger that didn't take up +128MB of ram. It would be nice if somebody would develop a native debugger in Java. Anybody know of any tools that meet this criteria?
Just to clarify, you are saying the program debugs itself, or is at least capable of displaying its own state?
Life sucks, but death doesn't put out at all....
--Thomas J. Kopp
I think that most of the debugging tools on the market are pretty good and users (developers) should be improved on the first place. For example in most of the colleges students get zero experience with debugging. Sure, the teachers tell us to use gdb or some other debuggers (that come with VC++), but nobody takes it too seriously. Most of my friends laugh when I start talking about debugging, testing and quality assurance. I am using gdb for my daily debugging and although it was pretty easy to learn, I wish somebody offeren a course on mordern debuggers in my computer science program.
I have had a progam that would run fine under the debugger in Visual Studio .NET, but executing the compiled version or even running with debugging would cause errors to occur. This is extreemly annoying.
If I have nothing to hide, don't search me
It runs during installation. To activate it, click 'I do not agree' when some incomprehensible gobbledegook called a 'EULA' is shown. A EULA is a kind of bug. Unless you refuse to accept, it will bug you again and again. Don't confuse bugs with viruses, however: Microsoft's debugger can't handle viral licenses, which is why they don't like the GPL. Once activated, the powerful EULA non-acceptance debugging option leaves your system bug-free.
- undoware.ca
A couple of observations:
1) Sophisticated memory use analysis tools, especially Purify, were rare 30 years ago. These catch many bugs before they cause symptoms. A must. Any production code *should* absolutely be run through one of the tools that instruments the code (like Purify), not just a malloc checker. Even all Free software should be run through one of these as well.
2) IDE's may lower the threshold for code prodcution for beginners, but rarely if ever improve the programming or debugging process. They neither help nor hinder experienced programmers.
3) The wider use of Python brings to the masses many of the interactive debugging luxuries previously enjoyed only by LISP programmers.
Yes, I could really use a debugger that runs backward for a problem I'm having recently. I wrote about it here last month:
The UPS debugger is a complete debugger, not just a GDB front end, that ran on Linux and solaris at least 5 years ago. It had a built-in interpreter so you could type in a line of C anywhere during debugging and continue. It also had a really nice and functional GUI, which clearly displayed where you are, what you're doing, and simplified debugging of large multi-file projects without special config files. I don't know if it's currently being developed; the whole thing was largely the effort of a single talented individual in the UK.
I usually add debug code by myself, they're far more useful. Debugger can do nothing but make me cry.
That's not writing code
Isn't it?
But if the debugger happens to be your way of confirming a piece of code is going to work, well, then you have a problem.
So how would you suggest confirming a piece of code is going to work?
Once your target is Windows, trace-style debugging becomes futile. Your only hope is binary-search, to try to remove and then add back in the offending API call to localize it.
I can confirm that this is a bad idea.
Forget the whales - save the babies.
Recently, I have been maintaing some (extreamly old) code written in VB3 at my place of employment. Let me tell you that I want to cry everytime I launch VB3 (and everytime my automatic 16-bit sub-system reboot hot-key is used to relaunch a crashed VB3). However, the tears of pain turn to tears of joy when I realize that I just spent the last half hour coding and the program stayed open the entire time! Errors, logic bugs, etc all cured while the program was running and never needing to rerun it. Edit and continue is the greatest thing ever! At a close second would be the ability to move the instruction cursor. Skiping or repeating a line of code is often very helpful, expecially when you use Edit and Contine, then want to immediately rerun the function to test the changes.
http://brandonbloom.name
Most debuggers do an adequate job of letting you examine and modify
data. Few let you understand the dynamic state of the program. I think
that's why printf is so useful -- you see the flow of execution of the
program, not just the final state.
Back when I worked on Purify I added a (hidden) facility I called "How
did I get here?". The Purify'd program maintained a fixed size
ring-buffer containing information about the most recent N function
calls. When a problem was detected you could then (in a standard
debugger) dump out this call history to help you understand just how the
program got there.
Imagine extending that idea: instead of recording function calls, record
(interesting) branch points. And have the compiler do it instead of
some third-party tool. Now you have something powerful -- you can look
back in time and (if you're lucky) see just where the program went off
the rails.
But I doubt this is true anymore as the VB we know and love is pretty much dead, it's VB.NET now, which is little more then a node to BASIC syntax for a .NET CLR.
-Jon
this is my sig.
"The debugger works by collecting "time stamps" which record everything that happens in a program. A GUI then allows the you to navigate backwards in time to look at objects, variables, method calls, etc.
This means that you can see which values are bad, then find where those values came from, who set them and why. This also means that there are no non-deterministic problems. You don't have to guess where the problems might be, you don't have to set breakpoints, you don't have to wonder which threads ran when, you don't ever have to repeat a program run. This is the debugger that you always dreamed about, but never thought was possible."
This is going to go down like a cup of cold sick in this forum, but here goes anyway...
It is better to need to use the debugger far less than to have an improved debugger.
A large class of bugs that arise in programs written in today's mainstream langauges (C, C++, Java, C#, VB) either simply cannot be expressed or are immediately detected by the compiler if one uses a modern, statically typed declarative language (Mercury, Haskell, SML etc.) The opportunities for run-time errors are far fewer in number.
The experience of many declarative programmers is that 90% of the time, once the compiler has accepted one's program, the program works exactly as intended.
On the other hand, experience with imperative languages indicates that 90% of the time one has to then run the program under the debugger in order to find out how it's going wrong. Time spent debugging often significantly outweighs the time spent coding in the first place.
Declarative languages have other advantages, even if one does have to resort to the debugger. For instance, since computations are generally side-effect free, one can re-run sub-computations without having to worry about affecting any program state. This allows for declarative debuggers, which help automate the process of identifying the point in a program that contains the first bug by remembering correct/incorrect answers from the programmer for each subcomputation of interest.
Finally, since declarative programs tend to be 10-20% of the size of the equivalent imperative program, and they usually don't contain all sorts of tedious bookkeeping code, there are consequently far fewer locations in which a bug can hide.
(For the record, modern compilers for Mercury etc. turn out code that is competitive in speed terms with C++ in most applications, and sometimes better, sometimes worse in others.)
System.out.println(..), cout, print STDOUT, Response.write, these are my debuggers, i RARELY have to get out jdb, or gdb.
I'm not drunk, I'm just in touch with pi.
Java H1-B "ploglammer" Mi So Solly roves Java!
Like most things in the computer industry we take the path of least resistance. It is easier to make better designs that are easer to debug then better ways to debug. If you have ever worked on legacy systems you will appreciate that it takes more time to fix some bugs then it does to rewrite the system so such bugs can't occur.
I figure the original author's confusion about the current state of debuggers is because he hasn't checked out VAJ. It is an excellent debugger (granted, so is VB). Sure there are drawbacks to VAJ, but nothing like the drawback to VB - having to code in VB! Talk about the dark ages.
If you can be certain that you won't ruin the garage or the SUV it sounds like a decent way of figuring out if the SUV will fit in the garage. I don't see how programming that way will ruin anything.
if you don't know that a particular piece of code will run or not maybe you've chosen the wrong career path
It seems then that a lot of programmers have chosen the wrong career path, because as soon as I change my colors to white text on black, a lot of programs become unusable or close...then there are a ton of bugs in Microsofts and others programs that appears might have been corrected hat they used this methos to make sure that their program works. Now seems like not to bad a time to mention one really annoying bug: When a website fails and I hit refresh and the website finally loads, the titlebar still display "Site not found".
Well as I pointed out. The whole thing, including debugging could be improved.
I wonder how many of the problems you and others listed could be alleviated by a hardware/software hybrid approach? Compiled code wouldn't make as much of a difference. Also one could bring higher level methadologies to a problem.
Whilst ideological preferences can get you so far, sometimes you need to look further and choose the best tool for the job. For example, instead of relying on a POS like gdb, use a decent IDE like Visual Studio with a well written debugger. The blind insistence that if something isn't GPLd it isn't worth using is one of the big problems facing the linux community as a whole. You can have ideological purity, or you can have the best software for the job. I know which I choose.
Been building houses since 1678, and the only joins I've ever needed were:
pegs
Seriously, an over-reliance on nails and screws is something I've *definitely* seen come into this industry.
Bah. Chimps.
Ah well, I missed all the discussion.
Most of the debugging I do is on IRIX using their cvd environment, ProDev Workshop. It's not great, but it has the following nice features:
What is missing are things like an array visualizer (I think): I had one of these for Digital Fortran on the Alpha. You could plot data from, say a 2D array, as a plane with the values in the array as the 3rd dimension. Nice.
Also, something like the KDE frontend for valgrind would be nice.
Smarter memory visualization would be nice. For example, on a simulation that we use, we have one machine that does the crunching, and another that acts as a communication frontend to some hardware. The cruncher and the communicator talk to each other over reflective memory. It would be nice to be able to describe the protocol they use to the debugger, and then see the message data in realtime. Or if you could simply see color coding for memory age or different colors for new vs. delete (or malloc vs. free), that would be okay.
Basically, I think the integration of a performance profiler, a memory visualizer, and a debugger with nice features would be very helpful. On the timing critical things that we do, adding printfs is not an option, because the delays they can induce absolutely break things. Sure, you can buffer them, and we often do that (even conditional breakpoints are often too heavyweight), but something that just gives you an idea of how things are progressing on the machine would be very welcome. Hell, for some things we output differential signals and then use a logic analyzer with advanced triggers to do bughunting.
I dunno. Sometimes I feel like I work in a unique environment, where something only really ``works'' when (a) it's functionally correct and (b) performance is good. For a lot of stuff, (a) is sufficient, and even that sometimes slides. I really like tweaking stuff to see if you can squeeze out those extra few microseconds.
A few thoughts from someone who has used and likes debuggers, which apparently is reasonably rare.
The only tool that I use for debugging is cout. What more could you possibly need. :)
well first...make a decent debugger...then people might even try to use them. I have tried to use a debugger...not had any luck. I even thought of trying to make one myself...no luck there either. Debugging i guess just takes a human mind to do.
Sorry for the anonymous coward posting, but printf is a horrible way to debug, except for the most naive of code (and in that case, why do you have bugs anyway?:)) Seriously, printf suffers from three major problems :
1) it calls malloc, so any memory related problems you are having will be altered
2) it is a stream oriented tool, so calling printf from multiple threads will not necessarily show you what you expect, and will also mess up timing
3) printf is slow. Unless you do a global #define to get rid of it in final compile (see 1 and 2 above for why this is a bad idea), you are killing yourself
I find useful and often use the Netbeans debugger. The debugger displays an object's encapsulated data in a traversable tree structure. However, sometimes to view some commanly used objects I have to traverse a few levels down the same way every time.
What I'd like to see is a configurable way to visually format an object's contents soley for the purpose of the debugger. Since it is for the debugger then a custom "debugger GUI" for a particular class could access all private fields.
For example, instead of traversing down a tree from a Matrix object into an array of doubles, then trying to figure out where m[9] lies in the matrix, I could write a "debugger GUI" for the Matrix class which would show my oftly used 4x4 matrices as a nice 4x4 table with all elements shown, and even allow me to make in-place modifications on the matrix easily. An ability to go from the visuall representation to the programatic representation of the object, and back, quickly would also be an advantage.
The question of whether a computer can think is no more interesting than the question of whether a submarine can swim.
It may have something to do with the kind of code that gets dumped on me, but most of the bugs I run into aren't insidous pointer over-runs and writes to free'd memory, they're logic errors and plain bad code.
The most useful tools I have are a roll of Scotch Tape(tm) and an assortment of highlighters.
The first task is to print out the thousand lines of code that should have been dozens of functions/classes/modules, tape it together and put it up on the wall.
Then I use the highlighters to mark the control blocks, and see why it's not working.
Until I can understand how the code runs on a macro level, it's useless to watch it with a debugger at a micro level.
While it's facinating to watch a counter run down to 0, it's not especially useful unless you know what it's counting, and why, and what's supposed to happen.
The fact of the matter is that the dominant style of programming (procedural) is pretty difficult to understand. The basic problem is that there is a lot of stuff going on behind the scenes that is not explicitly visible to the programmer. And so, if you want to investigate the behavior of a little piece of code you end up needing to run the context of the entire program, because that little piece depends on a the initialization of a pretty complex state.
The very proccess of compilation and testing is pretty time consuming and so people tend to test only at "milestone" stages - but adding a significat chunk of code can greatly increase the possible number of states the program can have, and typically only a tiny tiny fraction of those can be explored by the tester.
I know a number of programming languages, and for a few years I've been vaguely considering getting involved in open source - like most others, usually to improve an existing program to suit my purposes better. But invevitably it becomes a major effort to just figure out the structure of the program - what source files do what kind of thing, how the various modules are related and what sort of information they pass to each other in what order. Pretty obvious questions that are really hard to answer without painstaking manual labor.
Procedural programing is partly to blame, but also very important is the fact that most programming languages are generally lacking an overall organizing principle - so that for example there is a distinction between data and functions (like in c), or between functions and the code defining them (like most oo languages). BTW, the consequence of the latter case is that its hard to perform operations on the source code that try to discover structure, or automation tasks that could be used in something like for example a debugger.
At a meta-level, consider this: What does it say about the languages we use that it seems impossible to develop a systemitized way of discovering and teaching ourselves how a given piece of code works?
For an example of how things can be different, see the Mathematica programming language. Basically its like regular expressions on 'roids - you can transform absolutely anything according to patterns, which is made possible by the fact that everything is an "expression" which has a certain simple structure. Furthermore, every expression is self-contained, which makes it easy to pull out little sections of a program and test them with various input (also easily generated).
Of course the 1.8k pricetag is a bit steep - but they've been talking about releasing the language component for years and I predict its going to happen soon. So check it out.
They have to be. With all of the bugs within Windoze, noone would be able to get any work done. I don't know about VB personally (and by the way, VB wasn't developed by MS, they bought it), but ever look at all of the crap that MS-VC++ generates for you when you create anything involving COM?
A big part of the reason is that the languages paradigms that are popular today are directly copied from what was popular 5, 10, or even 30 years ago, with a little bit of a half-baked object system thrown on top (think C++, Java, etc.). Statically compiled "structured" programs don't lend themselves well to debugging, period. First of all, the debugger has to do a lot of contortion to do relatively simple stuff like stack and variable inspection. Then comes the problem of the "structured" style itself, which depends heavily on variable assignment and is very un-modular.
OO-design does reduce the granularity of program modularization and lessens the dependence on global variables somewhat, but inside, the objects are still programmed in a "structured" way. Even worse, object-overuse leads to a rat's nest of an object graph (my big beef with single-inheritance only object systems is that they encourage this).
For debuggers, steppers and stack-tracing to be really effective, a program has to be modularized with as fine granularity as possible. This is why functional and pseudo-functional languages generally tend to have and develop the best debuggers. Even before implementing any features, an interactive top-level is probably the best debugging tool available. But implementing stuff like advanced condition handling/breakpoints, stack-tracing/variable inspection, and function-tracing/steppers fits naturally into the language environment with minimal detriments to code size (anyone up for a little Java catch?) and performance.
In the great CONS chain of life, you can either be the CAR or be in the CDR.
-f: fix bug
What else would you need?!
In part agree with you. All of the modifications to the debugger discussed in this tread, help in specific cases but don't really help you understand the code in the big picture. I know when I am debugging, and when others are debugging, we build these large diagrams that show parts of the system in varying levels of detail. I don't know of any modeling tool that is tightly intergrated with the development enviroment, as in, if you change the model, the code changes and, more importantly, if you change the code, the model changes. Do you know of any products that do this (and can be used with C), or if this would be helpful for you?
We never have any problems with memory leaks or such, because we always wrap all OS interaction with our own subsystem that can do validation, we overload the "new" operator to take an extra name parameter, so that in debug mode every allocation is named so we can dump out any unfreed blocks on shutdown, etc, etc. Basically if you design each subsystem to be "bulletproof" (defensive programming--never trust the "user" of any API not to misuse it, even if you're making it for yourself!), and riddled with asserts, than bugs show up as an assertion failure or panic 90 percent of the time, usually right after the bug has occurred, and a bus error only 10 percent of the time. (Oh, and I guess the one cheat is that we have our own exception handler that traps these and does a stack trace, especially handy when you get an assertion in some very low-level function that's called in a zillion places. Then you can turn the crash address into an offset into the function, and look at the assembly, which is another good thing to do periodically to see how "honest" the compiler is...).
I know that we are very nonstandard in our practices, and that it probably comes down to personal preference, but I never wish for a debugger... usually the stuff that's really hard to track down involves understanding really complex state information, or doing things in real time, that a few watch variables would still be confusing--often it's faster to code up some sort of custom telemetry display into the program that shows the information in a way that's more understandable (such as a graph versus time or or a symbolic dump of a DMA chain)--make the computer work for you, instead of trying to do everything in your head. The "off by one" or pointer errors are usually much simpler to track down than the "conceptual" errors, which really need a thinking cap and the scientific method, not fancy tools. Also, not using a debugger makes it much easier to port to different platforms, because we're not heartbroken if our favorite GUI debugger isn't available for platform X. .sig--it's just something I typed on the last line.
--
This isn't a
http://www.signalscan.com/products/signalscan/inde x.htmll
http://www.novas.com/products/debussy.htm
Gimpel Software produced C-Terp before borland came out with turbo C. I wonder if they still use c-terp to develop PC-Lint?
#1. Languages dont kill programming, people do: i dunno about you unix types, but most of us plain people were born and raised on a staple diet of Dos and gw-basic, and the very technical lapses that you speak of were sheer joy to use and learn programming with. hey, i could redim my array at will- which means without knowing anything as esoteric as pointers and memory allocation, i could use the knowledge i had (arrays are things that hold a number of things of the same kind) and dynamically change the way my program worked (i can add more things to this array without having to know how many will be there) . And that line between those coordinates were right out of my coordinate geometry class, so i could relate. Hell i could even picture the line this way. so what if ole bacus and naur would frown at it? I got it, and more'n that, it showed a pretty picture on the screen, just like that! I wrote a whole 2d graphics editor with gwbasic. that was the reason the first c++ project i ever attempted was a 3d graphics engine.I went on to learn assemly language, pascal, c, c++, apl (well, i read about it atleast, and hand-wrote some programs - gotta love the dels and curls) and java.In fact, I learned to appreciate the features that other languages had because I had to learn how to implement those the hard way in basic.
bottom line - a good programmer always codes correctly : he'd make sure all his variables were strongly typed (even if he's using basic and it doesnt enforce types) if the code demands it, and he'll write perfectly object oriented code in C if thats whats needed.wake up and look beyond petty language differences to see the general programming form. there is no spoon.
as for vb, is there another ide that makes gui programming any easier - in the m$ world or linux?
#2.The end is near: building software will no longer be a cottage industry: Have you notice that software is generally moving to the more abstract level than concrete? java, ejb's and xml web services are heralding an increasingly abstractization (if thats a word, you know what i mean) of software. soon glue languages (read scripting) are going to be used more often in server side scenarios than before - not because core languages cannot do the job better, but because it will be more efficient to string together components (built using core languages) into bigger components, and eventually apps. So even if you thought of VB as a dimwit's scripting language, its going to be there, and used by the weekend code warriors and the joe nobodies, so help them god! if its no longer going to be monarchy of the nerds, why not join the others, and become their heads of state?
So pretty please (as Mr.Wolf said), with sugar on top, change the f***in attitude!
I can think of more than one situation where I could have used this feature.
If you're coding in Java, you might want to look into Log4J. You can assign priority levels to logging tasks (ie; "log this at debug priority") and then set via a configuration file what priorities for what classes will be logged.It isn't quite as low cost as no logging method calls at all, but it's impressively fast ... the Log4J intro page says ...
Given the general performance requirements (in terms of perceived user response time) of web applications, this is easily tolerable.
What's especially nice is that you can create a logging standard for all your classes. Log at the start and end of every method, log the constructor at the info priority. Log every error at the error priority. When it's time to switch to production, just modify a config file, and your logging switches from high levels of logging to only logging errors. To diagnose problems, just turn up the logging level for that class via the config file, and you get the level of logging you need.
I've been using Log4J for some time now, and I have to say that it's one of the most impressive things to come out of the Jakarta project ... and that's saying a lot.
"The only way you are going to check what you wrote is truely correct is to compare it against a formal specification - which is another topic entirely."
Which is why I advocate the approach (follow the chain) I mention. There's presently holes and weaknesses, but one day we will be able to go from "I have an idea" to here's that bridge you ordered. But we will have to let go of a lot of baggage and broaden our horizons.
... Only people are not adopting the new ideas.
:-(
For example, I used to work with a tool called BugTrapper from MuTek Solutions (it's now called AppSuite, and the company is now called Identify Software). It can record an application's runtime trace, replay it, rewind it and provide many more helpful debugging tools. Unfortunately it never caught on (maybe because of its price), and nobody has copied the idea to open-source tools
Imagine a graphical debugger with a scrollbar for time, where the top is "beginning of execution" and the bottom is "end of execution."
Two words for you, JMZ: self modifying.
Imagine a web pseudo-celebrity taking a CS theory class...
The trouble, as I see it, is that practically there is a huge amount of inertia when it comes to programming languages and methods.
.bz2), but I didn't have a hope of getting the main tar changed, because ppl don't like change. Another was a cleanup of ifconfig - but the changes weren't commited, even tho there were just bug fixes etc, because it would require testing on so many different platforms and libraries, that it wasn't worth it.
People still don't use debuggers (not saying good or bad, just stating it factly), people still use C very heavily, few people use lisp (although I do find more ppl using than I expected), and so on.
Visual programming never seemed to take off that well (the whole 'a routine is a box, connect the boxes' type thing), etc.
Going offtopic even more, I'm currently trying to redo all of the main command-line gnu tools, but am suffering from the same sort of problems. The command line tools suffer from really horrible problems that shouldn't exist, and the code is horrible for most of them, but they will never be fixed. For example, I patched 'tar' to autodetect the filetype (.gz or
My solution is to try to fix it all, break compatibility, and hope I can get enough done before I release it to have enough momentum to get somewhere.
Here is an experimental Java debugger which is able to remember every event happening in a program:
http://www.lambdacs.com/debugger/debugger.html
During a program run, it collects "time-stamps" for every event happening in the VM (using bytecode instrumentation). This generates a (potentially huge) trace of the program which your can then inspect in a GUI. The UI is quite powerful (although a bit complex).
Along with some polishing of the UI, the only thing it lacks is some kind of language to query the trace: currently you can only use the UI, which can become a bit tedious. It would be nice to have predefined queries to find common mistakes (deadlocks for example; yes, it works with multithreaded programs).
1. Cruel and unusual punishments involving pliers for engineers who don't use comments
1a And then I say comments, I dont mean a dissertation
1b or a running commentary
2. Doxygen, Javadoc or others
3. Decent structure to programs
4. Intuitive variable names
5. Verbosity/DEF_DEBUG switchgear
6. I could go on
IDEs are fine and dandy but it's another layer of strife. Could it be that IDEs spoil some programmers so much that they hack rather than design and implement - not a negative comment on XP BTW.
One of my bugbears is that debuggers don't seem to have caught up with object oriented programming yet. For example, often when I want to set a breakpoint, it would be really useful to be able to specify which object I want to break on as well, as I can usually narrow the problem down to a particular bit of code with a narrow set of objects. Now if there are thousands of identical objects like the one I want to debug, I have a problem. At the moment I have to solve it by finding a unique objet that will be activated just before the one I'm really interested in, breaking on that, then setting the breakpoint I really want, then running to that. Each time I do this I have to unset the breakpoint again, run to the first one, set it again etc.
This one single feature would greatly improve my productivity.
Also, simply generating a list of objects of a certain type would also be useful, so I can see how many there are in the system etc. And I'm sure there could be lots more OO-specific features other than these too. Come on debugger designers - please!
Skiing? Check out The Independant Skiers Portal
http://plan9.bell-labs.com/sys/doc/acidpaper.html
Acid: A Debugger Built From A Language
Phil Winterbottom
philw [ a t ] plan9.bell-labs.com
ABSTRACT
NOTE: Originally appeared in Proc. of the Winter 1994 USENIX Conf., pp. 211-222, San Francisco, CA
Acid is an unusual source-level symbolic debugger for Plan 9. It is implemented as a language interpreter with specialized primitives that provide debugger support. Programs written in the language manipulate one or more target processes; variables in the language represent the symbols, state, and resources of those processes. This structure allows complex interaction between the debugger and the target program and provides a convenient method of parameterizing differences between machine architectures. Although some effort is required to learn the debugging language, the richness and flexibility of the debugging environment encourages new ways of reasoning about the way programs run and the conditions under which they fail.
There are places where the networks are not touching,and there are places where they are-Boeing's Lori Gunter
I've been writing vc++ for a few years now, but one feature I'd REALLY like to see would be to be able to easily set conditional breakpoints on a particular instance of an object. In fact, more object awareness across the board would be nice. I'd also like to be able to be somewhere in a windows message handler, and be able to see where the message had come from. I'd like to be able to call functions from the watch window like I could in DEC FORTRAN. I'd like to see the VC++ debugger be able to enumerate over collection objects using for_each, and examine COM properties as if they were variables. I want the VB watch and immediate windows for VC++.
You can't win Darth. If you mod me down, I shall become more powerful than you could possibly imagine
I think when we get away from pure text development and start to really rely on graphics as an essential way to identify and componentize software development then debuggers will also improve.
Until then it's text for text...
Lots has been done to help this area, but only a fool would think debugging can ever be easy, if it was so simple, regular and predictable, then they wouldn't be bugs.
in my life God comes first.... but Linux is pretty high after that
Francis Smit
The Teso people held a superb lecture on reverse engineering and systematically finding security problems in binary code at this years Chaos Congress in Berlin.
They demonstrated a way to automatically analyze and segment binary code into basic blocks. A basic block is a segment of binary code that is being executed from top to bottoms, that is, it does not contain any jumps out of the block and is not the target of a jump into the code.
Team Teso then performed graph algorithms and data flow analysis algorithms on the basic block graph their primary tool produced. This is where things get interesting for debugging.
For example, the teso people were able to trace which basic blocks are being touched during code execution. You can imagine this as a graph of the program where each basic block is a block (node) and each jump is a vertice between the blocks. Upon execution, each basic block is colored as the code is being executed.
They also were able to reconstruct C program structures from binary, and they were able to reconstruct where data comes from that ends up in a certain buffer in a structure. This allowed them to check for matching buffer sizes automatically (!) and to retrace how to inject data into a program that has mismatching buffer sizes somewhere on the inside. Makes for some very easy, instantaneous exploit generation.
For more information, have a look at their slides from the lecture.
Kristian
But the real fallacy with "write-time debugging", and in fact all of the code-bug-free methodologies, is that there is very significant amounts of code that you must use to write your program that was written by someone else who is almost certainly not using your methodology (or, often, any methodology). So, even if your methodology worked on your own code it wouldn't work on the application as a whole.
I note that some of the most insidious bugs I've ever had to track down were caused by operating system errors. My favorite bug ever was under AIX where a call to select() with a 30-second timeout was returning in about 900 nanoseconds saying it had timed out. This caused a chain of failures. And, of course, it would only happen in some pretty unpredictable situations. In this case you needed two programs running under ptrace at the same time on the system for the bug to show itself - and it would only occur about one in five thousand calls to select() even under the failure conditions.
No amount of programmer effort on our part would have prevented this bug from biting us. We could certainly have put in a postcondition tester to check to see if the system call operated correctly (in fact that's how we worked around this problem) but can you realistically do that for every system call you ever make? Every library call you ever make? It's not practical to do so.
I'm all for doing things to minimize code errors, although to be completely honest the best method (as opposed to methodology) I've found to do that is to use languages that include their own run-time error checking, which are strongly typed, have mandatory exception handling, and which use garbage collection for heap management (Java being the only one I've used). The combination of such features leads to about 90% fewer bugs out-the-door and boosts programmer productivity by 200-400% over the long term versus something like C++ (that's data from several large programming projects I've been on).
It's that good because the environment tends to report problems as early as possible in the development process, when they are easiest to fix, and because of mandatory exception handling code more often gets written with failure handling in mind.
Even so, and even with methodologies that reduce bug rates even more, tools are often invaluable to producing good code. I find that heap inspection and profiling tools are very valuable for Java, for instance, as are techniques such as log instrumentation and assertion. (Unfortunately Java provides no facilities for any of this in-the-box, sigh.)
Anyway, to maximize programmer productivity and minimize bugs it pays to use an array of techniques and tools. Those who believe debuggers don't have their place, that they can be rendered pointless by technique, are badly mistaken.
jim frost
jimf@frostbytes.com
I find modern tools to be pretty sufficient. Some of the following features are quite important:
.NET for now), JDK 1.4.1 does this.
- Edit/Continue debugging.... VB used to do this (not in
- Watchpoints (when is something edited?)
- Jumping back stack frames (though you'll have to be careful to manually reset your shared state)
Tracking down bugs requires a certain kind of expertise. Usually it's harder to debug than to write new code, so that could be one reason why debuggers don't proliferate as much as modelling tools.
One way of gaining this expertise is to have experience in teaching other programmers in a hands-on course. You learn to spot common bugs quickly, and diagnose more complex ones. It's in an environment where you have 15+ people that all need your help at once... kinda pushes you towards honing that debugging sense.
In my experience, most "tough" debugging problems would have been solved if the developer just set the breakpoint and analyzed the code instead of sitting on their thumbs and thinking about it for 15 minutes. This might be fine for Kernhigan, Ritchie, Pike, and all those who suggest that "thinking" is the best way, but these guys also have *decades* of experience to do this without assistance. A debugger is a catalyst to this thought process.
Also, logging techniques are crucial, they isolate the location of a potential problem. But they're very time consuming to figure out WHY something is going wrong (because you never quite know what variables to dump out to stdout).
A debugger to seek stack traces & peek inside variables, change variable values, and edit/continue with your changes adds significantly to agility. It's partially why VB was so successful, and Eclipse is so popular in the Java world (and why most Smalltalkers have migrated to Java/Eclipse).
-Stu
They might incorporate LINT and run the program with mprof and thru a replacement malloc() to check leaks. Other than these, stepping into procedures and watching variables, what else is there to do with debuggers?? Theres no understandable direction to go from the debuggers' current state; theyre doing well.
On the other hand people seem to use debuggers less to take out program bugs. They rely more on reliable library functions, and post their problems in newsgroups for the library maintainers to fix. I personally use printf excessively to output the programs variables and state at each moment, then remove them from the final program. Its a more straightforward path than compiling with -g, powering up gdb and watching the variables, but then again gdb has its place.
"Give orange me give eat orange me eat orange give me eat orange give me you." -Nim Chimpsky
Is that because of the high level language, or because high-level languages encourage better coding styles?
I'm thinking of programming by contract here. My C++ and C is fairly sprinkled with assert()s, and my Java will be be likewise, when I move to version 1.4. With assertions on preconditions and postconditions and some unit tests, you can locate a bug to one method almost immediately, and if your methods are small (the current bast practice), that means only a handful of lines for you to inspect.
One of your repliers says:
If you need a debugger to understand what some code does, I suggest it it is badly written.
Ne mæg werig mod wyrde wiðstondan, ne se hreo hyge helpe gefremman.
I have found that debugging is great for stepping through complex algorithms but with technologies such as object oriented design, there is really not much of a need to debug. If you have your classes doing all the work, you can very easily determine the problem with your code. One problem that appears in a method of one class will most likely show up somewhere else where that method is called.
I use to debug a lot.. I have to manage a large, old (in every case) code in c (and it is running in driver aswell). It is all about bad design.. but if anyone make a new code, he will need debugers too, but not the same reason!
There are different reason to use one of them, so debuger tools have different way to use for diff. function..
If someone have a new, good designed code, he wont need deep debug..
but if someone have an old code, he need very clever debugging tool, if dont want to debug all the time..
Or there are driver writers, who need to debug sometimes in kernel..
different reason, different tools..
What I missing from debuger, is backword debugging.. if you find the problem, many times, you should go back to find the exact location of problem.. (I mean you find the problem, but you need to find the reason aswell) normaly you can walk back on the stack, but lot's of time it is not enugh.. some function is not on the stack enymore..
There is only one good solution: The simpliest!
I used DUEL about 5 years ago. It's an extension to gdb and similar in design to Acid. I am not sure if its features have been integrated into GDB now.
I envy you your success rate. :-)
Where I work, we are blessed with enlightened management and team leaders. Our tests are automated, and we have clean builds from the source control system and test runs overnight every night, with summaries generated and mailed to the team in time for the morning. To those who haven't adopted such an automated approach, I cannot advocate it enough. The difference between this and an environment where you're bogged down running numerous tests by hand according to different levels of test spec that took some poor soul weeks to write is staggering. This is from bitter, and then much happier, personal experience.
I'm not entirely convinced by the "test first" philosophy. That's always struck me as more of a political point than a practical one. Where we work, when we want to add a feature, someone first writes a proposal summarising the requirements. We then go through a very iterative development phase, effectively doing the design work by repeated prototyping, and then filling in the blanks.
The key thing we get right, I think, is that as we do this, and we're happy with the results, we actually generate the automated tests from what happens: our software can record the actions it's taken, and various checksum-type information about the results, and can later replay that recording and match (or not) against the previously saved checksums. Making a test is as simple as hitting the record button and then running through some actions that give the correct results, and running the test is as simple as playing back the test file that was previously generated.
It obviously requires a certain amount of effort to implement such a system: you effectively need some sort of "macro language" for the test files, and you need to have a checksumming facility to verify all the data in your system at a given moment and flag discrepancies. Furthermore, these do need to be updated when new features are added (extra macros) or new state is introduced into your model (extra info in the checksums). For the amount of time, and developer tedium, this saves, though, I'd guess it's an investment well worth making for many development shops. It's not even as much work as it first sounds, because many apps are essentially event-driven or based on some sort of command pattern architecture anyway, which means you've already got most of the framework in place.
Even with all of this in place, it's still quite possible to get bugs that are hard to find, though. Just because you know such a test failed, if that test was based on complicated processing, the fault could be anywhere within that process. Still, at least you can always look back at the overnight test records to pinpoint where something was checked in that caused the change.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
We're talking about real developers here, not php monkeys.
I know when we're desinging apps from scratch we can take time to follow a methodology and test appropriately, but not everyone does, and if you've ever inherited a large codebase that you *MUST* fix and was neither well designed, tested, or even documented, some tools would be invaluable:
- Memory leak detection. After 100K hits, Java and FastCGI's can both be a victim of this, and few tools detect it well. (And it's not as hard to write as you think!)
- Flow navigation. Having once inherited 200K lines of broken, undocumented servlet spaghetti, I needed tools which would not only breakpoint, but graphically illustrate surrounding logic, active threads and active heap.
There are static tools which do this, but none integrate directly into debuggers.
- Model integration. If the app is small enough that you can add couts/printfs/printlns, this is overkill. If the app is 500K lines and has ~1000 classes, its very handy to see the design pattern of the classes containing the bug.
- JVM/WAS/Apache/IIS integration, so modules may be monitored in-situ.
Beware: I believe all are created equal, and have the right to life, liberty, and the pursuit of happiness.