Hello

Would anyone like to share their tips & tricks for debugging functions & whole programs in C++.

I find I suck at debugging :P & really dont look forward to having to go through my functions again to see if there are any loopholes etc so if anyone could provide some tips & tricks it would be really helpful.

I have searched alot and there aren't many places to find advice on how to do it & I find it really tedius :P

From my experience I would offer this advice:
- DEBUG AS YOU GO - Every time you write a function or every hour or sumthing like that. Going over your whole program is a b***h, lol, :P

- When debugging functions that take in input - list all the possible input that someone may enter then test ur function with it, make sure it either works or it outputs "invalid input" or etc, so that it doesn't crash.

Please share any other advice for debugging :)

Recommended Answers

All 10 Replies

If your code has a lot of pointer stuff in it, it's often a good idea to run "valgrind" every once in a while to check for memory leaks.

It's often a good idea to create some sort of "debug output" function for a class to print its state. That way, if something isn't working as it should, you can just print the object's state and troubleshoot from there.

If your program segfaults, gdb can often quickly track down the problem. (Assuming g++ compiler here ->) Compile with -g flag, and run gdb ./yourprogram. Type "run" to execute. Type "bt" to see what function called what, and type "frame" to see the current stack frame. Type "print your_var_here" to see the contents of any pointer, int, .etc Type "up" and "down" to navigate the stack.

Never rely on a pointer's state! Always check for NULL and/or unacceptable conditions. You can't bee too careful (for the most part :p)

You can see that, at least in my experience, debugging is often a result of some sort of pointer / memory error. So, finally, avoid pointers when possible and use references instead.

Would anyone like to share their tips & tricks for debugging functions & whole programs in C++.

Learn how your computer works! :) I found that understanding the machine and things at a lower level like assembly and how the OS manages programs/memory really helped my debugging. It also helped improve the quality of my code.

I put in a lot of cout statements, like:

char c[3];
cout << "Got this far\n";
c[0] = 'H';
cout << "Now I'm this far!  Cool.\n";
c[1] = 'e';
cout << "Hot damn!  I'm this far\n";
c[2] = 'l';
cout << "Oh yeah!  Stylin'. I'm here!\n";
c[3] = 'l';
cout << "Uh oh.  Now I'm this far...\n";
c[4] = 'o';
cout << "!**##%$. This should have crashed by now.\n"[B];[/B]

That sort of stuff. You're hoping to see "Oh yeah!", but not "Uh oh." Probably not the most efficient way, but it 's cathartic in that it allows you to vent at the computer in your debugging statements/error message. Just remember to take it all out when/if (hopefully) everything is solved.

I put in a lot of cout statements, like:

char c[3];
cout << "Got this far\n";
c[0] = 'H';
cout << "Now I'm this far!  Cool.\n";
c[1] = 'e';
cout << "Hot damn!  I'm this far\n";
c[2] = 'l';
cout << "Oh yeah!  Stylin'. I'm here!\n";
c[3] = 'l';
cout << "Uh oh.  Now I'm this far...\n";
c[4] = 'o';
cout << "!**##%$. This should have crashed by now.\n"[B];[/B]

That sort of stuff. You're hoping to see "Oh yeah!", but not "Uh oh." Probably not the most efficient way, but it 's cathartic in that it allows you to vent at the computer in your debugging statements/error message. Just remember to take it all out when/if (hopefully) everything is solved.

This thread is years old now,However I've see something wrong idea here.

Using cout is really a frustrating thing to do.Because the debugger support all these
functions. However it's oky to use something like this.

#ifdef __DEBUG__
print_memory_dump();
#endif

No offense with you but this is really a bad debugging tip.

Dumping a thread like this is not nice, but while we are at it. For outputting, I like this better:

//in some basic header of your software.

#ifndef DEBUG_VERBOSITY
#define DEBUG_VERBOSITY 5
#endif

#define DEBUG_NOTICE(X,Y) if(X <= DEBUG_VERBOSITY)  std::cout << __FILE__ << ":" << __LINE__ << " " << Y << std::endl;

//then in the code:
int main() {
  //..do something, then output an important debug notice:
  DEBUG_NOTICE(2,"the last operation failed! With error '" << error_message << "'")
  //..do other stuff, then output a not-so-important debug notice:
  DEBUG_NOTICE(8,"reached this point without segfault!");
  ... etc ...
};

hello mike_2000_17,

could you explain a couple of things about your code offering. I'm not that experienced and only write for fun/pleasure but would love to understand whats going on there with a view to implementing something similar in GUI's.
1/ What is the '5' for at the end of line 4 ?
2/ In 'simple-speak': what exactly is line 7 doing/saying? And finally - for the moment :-)
3/ Lines 12 and 14 respectivally: the '2' and '8'? - Must be linked with Line 7 only I don't see how.

Thanks for your time & patience!
David

Ho, well the thing I posted is the classic debug print MACRO.

Line 3-5: This checks if the #define symbol "DEBUG_VERBOSITY" was defined through the compilation command-line arguments (like -DDEBUG_VERBOSITY=4), if not, it will define it as 5. This is the verbosity level of the debug output. This means if the first number in the call DEBUG_NOTICE() is smaller than DEBUG_VERBOSITY, the notice will be outputted otherwise it won't.

So in line 12 and 14, the 2 and 8 are the "importance rank" of the notice. This way you put the more important messages to print with a lower number (like 1 to 4 or something) and lesser important messages that you would only use when you are doing really deep debugging, would have higher numbers. This way, when you compile with low verbosity you get less debug printouts and you can turn debug printouts back on by increasing verbosity. This way you don't have to manually take out the debug printouts once you have a working software, you just leave them there and compile with verbosity 0 for the release version.

Now, line 7 is a MACRO, of course, the first parameter is that "importance rank" for the message, while the second parameter (Y) is what you would put "cout << HERE << endl;" to print the message on the terminal or console. The only other thing there is __FILE__ and __LINE__ which are standard special defines that all compiler provide, __FILE__ is the name of the source file and __LINE__ is the line number where that "__LINE__" token is. So the above code inside a file called "test.cpp", if compiled with -DDEBUG_VERBOSITY=5, would output:
/home/username/mypath/test.cpp:12 the last operation failed! With error 'error_message'

or, when compiled with -DDEBUG_VERBOSITY=10:
/home/username/mypath/test.cpp:12 the last operation failed! With error 'error_message'
/home/username/mypath/test.cpp:14 reached this point without segfault!

Hopes this can be useful to you.. look up debug print or dPrint or the debug print macro.. this is a very common little trick.

That's a great idea. We've all spent lots of time trying to sort out where a bug starts - this sort of code could save hours of searching for someone like me.

Just one further question. If the DEBUG_NOTICE(nr,"Some text") is to be shown in, lets say, a MessageBox, would it be ok to point the whole thing at a string?
eg:
AnsiString theString = DEBUG_NOTICE(nr,"Some text");
....
Application->MessageBox(theString, "Alert!", MB_OK);

Are there any real benefits or advantages of using a debug macro against 'assert' - other than you don't have to include a header? bcb 5.0 doesn't offer much info..

>>If the DEBUG_NOTICE(nr,"Some text") is to be shown in, lets say, a MessageBox, would it be ok to point the whole thing at a string?

Look at the definition of the DEBUG_NOTICE MACRO, it uses "std::cout << Z << endl;", this outputs to the console (DOS command prompt in windows). It's not a string. You could make a macro just the same for any other text output (I personally would not recommend MessageBox, because you will spend all your time clicking on OK to go from one messagebox to the next.. a console or TextBox print would be more suitable (or TMemoBox if you are using VCL)). Anyways for a MessageBox, you can define the MACRO differently:

#define DEBUG_BOX(X,Y) if(X <= DEBUG_VERBOSITY) MessageBox(NULL,(std::string(__FILE__) + ":" + itoa(__LINE__) + " " + Y).c_str(),"Debug notice", MB_OK);

Note: I only know the win32 messagebox call.


>>Are there any real benefits or advantages of using a debug macro against 'assert' - other than you don't have to include a header?

Well first of all, you have to put the debug macro in a header with header guards, otherwise the compiler will say "multiple definitions of the macro" if you use it in multiple source files. Second, an assert is a completely different thing that serves a completely different purpose. An assert is just a way to abruptly stop the execution when an error condition is found. The debug print macro is used to output a whole bunch of information (depending on verbosity) about where to code has come to, what are the values of the variables, etc. to give you real-time information as you run the program to help you understand what is going on, especially in multi-threaded applications where breakpoints and code-stepping are not an option. It is not meant in any way to stop the execution on an error condition. It is not for errors, but for general run-time information that an expert-programmer of a software finds useful in debugging (that's also why a messagebox is not really appropriate because it pauses the execution at every new messagebox).

>>bcb 5.0 doesn't offer much info..

Wow, bcb 5.0, that's a vestige of the past! I know the VCL/CLX is great, but you might wanna consider moving to either a more recent Borland product (CodeGear or RAD Studio or whatever they call it now), or moving to a more mainstream IDE like Visual Studio or Code Blocks.

>>Note: I only know the win32 messagebox call
Point noted

>>Wow, bcb 5.0, that's a vestige of the past! I know the VCL/CLX is great, but you might wanna consider moving to either a more recent Borland product (CodeGear or RAD Studio or whatever they call it now), or moving to a more mainstream IDE like Visual Studio or Code Blocks.

Point *really* noted

I'm going to have a real look at upgrading now as I don't want a problem later with forward compatability! Haha, I'm probably there already!!

OK. I'll leave this at that for now.

Thanks for your effort & time (both +'v signed)
David

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.