Assuming you learnt programming in a formal situation, did debugging get taught in any significant way?
Printable View
Assuming you learnt programming in a formal situation, did debugging get taught in any significant way?
Nope, I still don't really know how to do it much.
I used to just cout my code all over to find out what was happening.
I learned at work to investigate a core with the debugger (command line gdb).
I should really learn how to debug a running program... a colleague kind of showed me once, but I forgot...
Am I being a hopeless optimist in thinking that the What's debugging count will stay at zero? :rolleyes:
Nope, we weren't taught how to use the debugger, actually, there was only one C++ course at the entire university. All the comp-sci courses were Java except for the graphics courses which were of course C. The one C++ class had a professor who really didn't know much about it. His idea of debugging was:
Useful for some things, but not most.Code:void method(void){
//Some code
cout << "Made it here" << endl;
//Some more code;
cout << "Made it here 2" << endl;
}
Only had one intro to C++ class that barely even covered the basics, but debugging wasn't mentioned.
Interesting poll John.
I believe that debugging should be part (or perhaps a parallel course) of a programming course in college. When reading the poll I first thought of marking *Some help was given*. Then, I realized that the correct answer in my case would be *No*.
I did get some help, but it was really something like this: If you want to inspect variable values run your program line by line. Just hit FX instead of FY and place some "bullets" at the places you would like it to stop. Then hit FW to execute a particular statement.
That's everything I was told about debugging at school. This is so far away from actually understanding how debugging works and all the help you can get from it that I decided to vote *No*. The worst part is that I know people that still think that debugging is just that.
Debugging could be considered an art just as programming. We should be taught how the attachment process work, how symbols are generated, how to analyse the stack, how to analyse core dumps, memory layout, among others things. Also, debugging can be a very creative process when you have non-usual situations in which you can't inspect things easily or directly.
I'm not an expert debugger. When possible, I try to learn things and work on it. But surely, school could have helped me better just like it did for writting code. Both subjects are important and complementary.
It's not just learning how to use the debugger that's important (assuming the platform you're working on has one!) but also designing for debugging.
On some embedded projects that I worked on many, many years ago, the software was compiled on a 286 MSDOS machine and blown into a ROM before it could be tested. Very early on I designed in a diagnostics port into all of the hardware so that I could plug in my debug box (LED display, switches, RS232 port) to get debugging information out.
Nowadays I work on Windows based projects, but I still design in debugging. Now it comes in the form of compile time & run time asserts, logs and exceptions. All are built into the code from the very beginning.
It wasn't covered extensively in my college-level classes, no. However, they did at least touch on it when I was at American Computer Experience summer camp on the BU campus, and in my high school APCS course.
The real question is, were you taught how to use man pages?
That said, could anybody point me to a good gdb debugger tutorial ;)
You need another poll choice - something like:
"Self taught programmer, but is proficient in debugging."
Debugging is probably the most important skill a developer can, um, develop. It's not just being able to effectively use your debugger (whether it's integrated in an IDE or standalone), but also being able to set up the environment so that your program can be debugged.
Too much time is wasted on ineffective debugging techniques like cout or putting in message boxes. In my opinion these should be a last resort over using more advanced debugging tools.
Most programmers use their IDE for debugging, which have wrappers around gdb. XCode's debugger is by far the best, but if you're on Windows, Code::Blocks has a nice interface to the debugger. Just take a look at the Debug menu, most of it is pretty self evident.
In this day and age of interactive debuggers, it's incredulous (at least to me) that someone using, say Visual Studio, would have a problem with a relatively simple program and not be curious as to what the "Debug" menu item on the IDE is supposed to do. But in too many instances, you have posters not using their own initiative in figuring this out . I would expect this scenario -- "Debug menu item? Let's see, what does this do? Hey, look at this! I can see my program run under my control. That's cool". Nope, you get the "I never used the debugger" responses.
When I was going to school, there were hardly any interactive terminals in schools, let alone interactive debuggers such as Visual Studio's or gdb. This was at the latter part of the punchcard era. In my case, you had to go through the code by hand to make sure the program was error-free. You would then hand your punch cards over to someone you didn't know in a room, and waited several hours for your output to appear on paper. Now given that scenario, you had to learn debugging very quickly or else you would never get your programs completed.
Regards,
Paul McKenzie
This is really a general attitude issue towards using computers/technology. For a great many people the train of thought goes something more like "Debug menu? What does this do? Hm, I don't know what it is, better leave it alone - might break something".Quote:
But in too many instances, you have posters not using their own initiative in figuring this out . I would expect this scenario -- "Debug menu item? Let's see, what does this do? Hey, look at this! I can see my program run under my control. That's cool". Nope, you get the "I never used the debugger" responses.
Even among professional programmers I've known more than a few people who were effectively novice computer users. They have their language(s) and suite of tools that they're familiar with and good at, but throw something different at them, take them out of their comfort zone, and they're completely hopeless without someone to hold their hand and guide them step by step.
One of my intro C++ classes had a special one-time session outside of class about using the debugger in Visual Studio. Being a stupid freshman I didn't go, and to this day I debug by planting couts everywhere. Gotta look into a tutorial one of these days.
There isn't much to teach about debugging is there? There's no special theory behind it or anything.
It's much better to introduce tools of this kind as a natural part of the laboratory part of courses. For example in some basic programmming course you learn how to handle an editor and a debugger, in an electronics course you learn how to handle an oscilloscope, in a microprocessor course you learn how to handle a logic analyzer, in a biochemistry course you learn how to handle a PCR machine, in a type writing course you learn how to handle a coffee machine, etcetera.
There are examples of cases where an "instrument" merits a course of its own but generally they're best introduced in the situation where they're naturally used. I'd say debuggers fall into this category.
I would even go as far as to say that if the university/college you're considering is offering a course in program debugging you should have second thougths. This is a course you would rather expect at a vocational training centre.
What is that ?Quote:
attachment process work, how symbols are generated, how to analyze the stack, how to analyze core dumps, memory layout
Basic debugging seems like common sense to me. As John pointed out earlier the best way would be for the teacher to explain programming techniques during the class that will lead the programmer into learning how to use the debugger in the laboratory. I think that you could have part of a design course dedicated to error handling (including exception handling) / debugging. Unfortunately, during college I never really had a lot of guidance from the teacher. Then again, I went to school for engineering so computer programming was not really my major. I only really had a couple of classes on HOL programming. If I were a computer science major I would highly expect to take classes where debugging / error handling topics were covered in depth.
Really, I'd expect that focus more in a software engineering major. Maybe in an introductory CS course.
A CS major is more about learning algorithms and data structures and complexity theory and the like, than about the practicalities of coding. They pretty much assume you're going to figure that out on your own, especially if they aren't having you use an obscure language like Lisp or SML.
I answered no, even though my major in college was Computer Science. They showed us a quick way of building a debugger version in Visual Studio and briefly mentioned that we should not port our programs like that. The major push was toward learning the language itself (as in regards to c/C++/MFC.) So having all that knowledge in itself I would struggle a big time, like pretty much so many posters on this site do, as you have already noticed.
I have to confess though that most of my debugging knowledge came from my previous "hobby". (And I feel really bad about it.) One of my friends back in college introduced me to SoftICE and to ways how to bypass a software registration by disassembling/debugging a program to find out the part where the "fix" had to be made. I know, it's bad, but I was stupid back then. (It was almost 10 years ago.) Now I can use that knowledge to not only safe-guard my own software and software of a company I work for, but it also helps me to better understand the debugging process. Here again, I'm not advocating people to go into hacking someone else's software, it's simply a weird way how I came to it.
It also brings another point (which is, I guess, is an advanced debugging technique). Besides simply using a debugger and being able to place a breakpoint and catch a moment right before the "bug" happens, it is also important to be able to analyze the bug itself. In this case, what happened to be an indispensable asset for me, is the knowledge of the machine code and assembler. The Visual Studio has a less known feature (that is disabled by default) to not only see the source code but to also see a machine code for each line (called Toggle Disassembly, or Ctrl+F11). By seeing the disassembly for each line of code you can easily track down any hidden calls and registry/memory corruption that in a source code would appear as one line. That saved my butt many times.
One more thing I want to add here, is that my way of designing software includes insertion of the ASSERT/VERIFY macros (for MFC) into as many functions/methods in my code as possible. They do checks on any possible erroneous situation, thus, in a way, by using them I'm preventing a possible need for debugging while writing the code. In this case, if an assertion fires I can pretty quickly trace it back to its origins since the whole source code is packed with other assertions (that didn't fire before this one) and thus that in itself provides me with the very moment when glitch occurred.
Really quickly to illustrate what I mean:Code://Say somewhere in a code, we need to read 'n' elements in the memory array 'pBuff',
//starting with the index 'i', where 'sz' is the size of an array in array element count
ASSERT(pBuff); //Simple check that an array pointer is valid
ASSERT(sz >= 0); //Make sure size is correct
ASSERT(i >= 0 && i < sz); //Make sure index is valid
ASSERT(n >= 0 && i + n <= sz); //Make sure number of elements doesn't go out of scope
ASSERT(!IsBadReadPtr(pBuff + i, n * sizeof(*pBuff))); //Longer check -- use only if you get 'pBuff', 'i' and 'n' from outside of your program. In most cases it's an overkill to use this line
//Reading itself may be necessary to include into an exception-safe block
//All exception handling will stay in a Release build, unlike the ASSERTions.
PS.No so, hah :D
I'm not at all sure a debugger is the right tool for the kinds of problems usually posted at this forum. Simple tracing seems good enougth to me.
What I feel is generally lacking among posters is a program development methology. I was taught something called Stepwise Refinement. Somewhat simplified this means that you start with a small working program. Then you change it in small increments and make sure it still works after each change. In the end you have a big working program without having to debug anything.
For some types of programming that's good enough. For anything really math-heavy, especially research where the algorithm you're implementing may not be well-understood, I suspect it might not be.
Of course as always, debugging is a combination of approaches used as appropriate. The debugger is only one of many options.
My list:
Assert
Log File
Debugger
Message box
That's for big projects, for small projects, the log file is at the bottom, but Asserts are always on the top for me.
I use the log file instead of the debugger so that I can program very quickly, once I've got it all written and it's working well, then I go back into the debugger and fine tune it, adding to the stability.
I suppose my increased usage of STL and Boost are following this philosophy as well. I'm a big fan of the "if it compiles it's probably right, and if it's not it'll throw an exception" style of coding.
Asserts being part of that category, since even though they're not *really* exceptions they behave the same in gdb---they halt execution at the point of failure for you.
Good in theory, impossible in practice.
Such things help. However, they can't prevent all bugs, so as I said before: Debugging is a multi-approach discipline.Quote:
Not to introduce any bugs (that needs debugging) you use a proper program development method, like for example Stepwise Refinement.
I didn't say anything about your pet method. I said it's impossible to avoid bugs entirely all the time. But you'd know that if you bothered to pay attention to which part I quoted.
The debugging tools I use are all dependent on the nature of the bug I'm trying to find.
I find that algorithmic bugs are often easier to solve using the debugger; I can see the variables change, modify them if necessary and step into functions to see where execution differs from that I expected.
In simple cases I may just bring up a dialog box with the values of interest.
Other problems can sometimes be intermittent; Our applications are realtime, multi-threaded and asynchronous. The debugger is usually useless in this case for tracking down non-complient behaviour. In this case I resort to our event log. Our event logging system allows us to enable/disable logs through an external file, so event log code tends to stay in the source. The overhead of testing for an enabled/disabled log has been designed to be extremely low.
As a general rule in building the code, I tend to write in a functionally modular style; Each area of functionality is as self contained as possible and as near as possible, testable in isolation. Any functionality that can be identified as part of a more general case will often be written in a generic fashion and added to our library, often customised by the use of polymorphism or dependency injection. This allows a resource of tested and debugged code to be used with confidence in new applications.
At the lowest level, exceptional errors, such as out of bounds or illegal parameters, are trapped using exceptions which log the class, function and reason. These can be switched off using a compiler switch when necessary for performance critical code.
I think that modular construction is a necessary addition to that, otherwise software can grow into a large unmaintainable monster, even though it may be functionally correct.Quote:
In fact Stepwise Refinement is the mother of all program development metods.
Our old library contains an image class that started simple. Stepwise development saw it increase in functionality over the years. Unfortunately it started to become a massive class that contained every 'useful' function that various coders came up with. Our new library now splits the responsibility in STL fashion i.e. container/iterator/algorithm. Now stepwise development involves merely devising an algorithm that conforms to the iterator interface.
I mostly find debugging the program very difficult when using library(.lib) or dll.
What is your opinion ?
When I use logging, I prefer a logging mechanism that is capable of different log levels and has indenting. With this logging framework, I generally log when I enter and leave method (usually logging additional info in these calls as well). I just find it easier to read the log file that clearly shows where you've entered and exited methods as opposed to a left-aligned log.
All the methods you suggested
Debugger
Log File
Event log
Trace output
Message box
with the exception of the debugger, require you to modify your code specifically for the purpose of debugging. That in itself aside from being messy and time consuming can alter the behavior of the program.
Among other things., the debugger lets you watch your program run step by step. It lets you view and jump around in the call stack and examine the local variables at any point in the stack. It lets you watch variable assignments as they occur in real time or even change the value of variables while the program is running. It lets you see return values from functions and values of arguments passed into functions. It lets you watch variables or memory locations and break when they change. It lets you modify your code and continue execution right where you left off.
You normally do it like this:Code://On a global scale
#define DO_LOG_MY_EVENTS //Comment this line if logging is not necessary
#ifdef DO_LOG_MY_EVENTS
#define LOG_MY_EVENT(a, b, c) LogMyEvent(a, b, c)
#else
#define LOG_MY_EVENT(a, b, c)
#endif
In most cases it will not interfere with the original flow of the code.Code://And then when you need to log an event:
LOG_MY_EVENT(__LINE__, __FILE__, _T("Whatever else"));
Declaring any global variables would not be good in case of multi-threading.
Question to all of you, do you use Windows built-in event logging, or something that you came up with yourself?
I've found as time goes on, the logging frameworks become more sophisticated. I prefer a framework that has multiple output targets (Console, debug trace, logfile, event log, etc) and on that you can externally change settings such as what components to log, detail level and so on.
As far as what I use, I've used and use both built-in frameworks and homegrown ones.