tags:

views:

398

answers:

8

What are the expert debugging hints for your favourite language, you think everyone should use?

As an example, I'll provide my C++ debugging hints, that between them help me shake out most of the bugs I come across, in this often hard-to-debug language.

C++

  • Increase the warning level of your compiler to maximum, then stop those warnings which occur a lot and you've decided you don't care about (for me it's unused parameters). g++ doesn't warn about missing return statements in functions (a problem I find frequently) until the warning level is very high.

  • Learn how to turn on your compiler's debugging standard library, and use it! ( -D_GLIBCXX_DEBUG for g++). This finds lots of errors, and also helps show exactly where the errors occurred.

  • Always, always, always run your code through a really good memory checker, like valgrind, and fix all the problems it produces.

A: 

Always have "err, hr" in your watch window. I will show the result you would get from calling GetLastError. And its dynamically updated when you step through the code.

Magnus Westin
+4  A: 

Learn what the different magic numbers means that VS memory handler writes when it handles memory.

0xCDCDCDCD Allocated in heap, but not initialized. By malloc
0xCCCCCCCC Allocated on stack, but not initialized.
0xDDDDDDDD Released heap memory. By free
0xFDFDFDFD "NoMansLand" fences automatically placed at boundary of heap memory. Should never be overwritten. If you do overwrite one, you're probably walking off the end of an array.
0xFEEEFEEE Deleted memory by HeapFree
0xBAADF00D Allocated in heap, but not initialized. By HeapAlloc
0xABABABAB Dont know. If someone know what this means, please add that.

Magnus Westin
Isn't this specific to some environments ? Google seems to be saying Visual Studio.
philippe
I assume that's what Magnus was referring to with the 'VS' reference above...
Timo Geusch
oops - didn't even see it, thanks.
philippe
+2  A: 

A couple of my own, from spending too many nights debugging stuff that the compiler or runtime environment could have warned me about if I'd used it properly:

  • If you're doing anything with pointers in C++, assert() them wherever suitable. In fact, assert()ing invariants is generally a good idea and can cut the debugging time on that one obscure bug from weeks to minutes. Just remember to turn them off in the release build. Oh, and don't put anything in there that has side effects, otherwise you'll be debugging your release build for a little while. Don't ask me how I found out that one
  • In a similar vein, BOOST_STATIC_ASSERT can be extremely helpful in checking for discrepancies you can check at compile time
  • Memory debuggers like PurifyPlus or valgrind are excellent time-saving devices and should be on every developer's machine
  • Learn how to use the debugger properly so you can harness its full power instead of just using it as a device that allows you to single-step through your code
  • If you're really stuck, explain the problem and the code to a colleague
  • For C++, a tool like FlexeLint/PC-Lint can help pinpoint a lot of hard-to-find stuff once you configured it properly. You'll have to invest the time to configure it otherwise you'll drown in warnings
  • If you're writing C++ and you're using the standard containers, write code that uses iterators and let the debug version of the runtime (or a debug STL) catch your off-by-one errors. If you use indices to reference elements in, say, a std::vector<> you'll have to find those yourself
  • Run the code through different compilers if you can and pay heed to the warnings each one of them produces. However make sure that they're at similar levels of language compatibility (no point in running modern C++ code through MS VC++ 6) otherwise you'll end up chasing problems that aren't really there.

Ideally, you should try to catch problems before you need to fire up the debugger - anything you can tweak such that it creates a compilation error is much easier to fix compared to tracking it down in the debugger and then fixing it.

Timo Geusch
A: 

Not sure if this counts as debugging, but for C and Objective-C code I find the LLVM/Clang Static Analyzer to be invaluable. Helps spot bugs, memory leaks and logical errors even before you see their effects.

Stephen Darlington
+1  A: 

My debugging (PHP) consists mainly of an addition to the last line of the (passworded, IP-locked) page:

echo '<pre>'; print_r($GLOBALS); echo '</pre>';

If the problem ain't in there you can debug 'properly', but 9 times in 10 it'll jump out from just that.

A: 

In Visual C++ debugger you often find yourself in an inline single-line function, which you can't step into and view its local(s). For example:

  class foo
  {
     int bar() { int i = func1(); int j = func2(i); return j; }
  };

To show the value of i, you need a stack frame. But the debugger wouldn't step into bar() and show you the contents of i.

The trick here is to enable inline assembly in the debugger. This expands the processor instructions of the functions, which are more than a single line now. So now you can step into the function and query the variables.

Or maybe there's another way of doing it. :)

A: 

I have no references for this, but I was told the 0xABABABAB address means 'memory beyond the bounds of allocated memory'. Hope it helps.

Hazel
A: 

Occasionally run your Release build, instead of your Debug build. Some bugs only happen when optimizations are turned on.

ajs410