Skip to main content
  1. Teaching/
  2. teaching/

·6 mins

Quick Tips on Debugging C++
#

Figuring out what has gone wrong and how to fix it is possibly the central skill in all interesting work, both inside computer science and outside of it.

This is not a guide on general debugging techniques. For that, look at Julia Evans’s blog or Regehr’s guide. Both are solid guides for basic debugging techniques.

If you want to learn how to use debugging tools, this is a great thing! Look at this guide on using a debugger and this guide on using gdb specifically. You should also have a rough idea of how to use valgrind. However, while this guide will mention these tools, it is not a guide on tooling.

This guide is specific to C++: how to deal with compiler errors, what information to look for when dealing with certain errors, and “holding patterns:” common information collection techniques you can use to quickly get more information about the problem.

  1. TOC {:toc}

Compile-time errors
#

While compile-time errors are vastly preferable to runtime errors, this is little comfort when you’re stuck facing an undecipherable compiler error. This is not intended as an in-depth debugging guide–rather, it’s intended as a way to identify what the heck the compiler just hit you with and where you should be looking for a fix.

As a general rule, when presented with multiple compiler errors, fix the first error first, then recompile. Compiler errors can sometimes chain into each other in a way that makes subsequent error reports incorrect, and it’s a pretty crummy feeling to spend 30 minutes fixing an “error” that isn’t actually an error.

Template Errors
#

Template errors can be identified by the fact that the output for a single error is often absurdly long.

Their structure is often rather unique as well: these often structure themselves as an error at the top, and then a HUGE list of templates that were tried. This usually results in a bunch of messages like template deduction failed or candidate ignored. If you see a whole bunch of these messages, then scroll up to see what looks like a type error, you’ve probably got a template error on your hands.

When facing a template error, the most important things to extract are where the error comes from in your code, and what the template is that’s failing. This is usually found at the very top of the template error.

Once you’re at the start of the error message, scan the left side of the error message for a file that you can recognize as belonging to you. If you reach the section where it’s listing the templates it tried, you’ve gone too far. For example, in g++ 9, the error might say problem1.cpp:9:92: required from here. Once you’ve found this, go to your source code and look at the line that’s causing the error. Note any functions or methods that you might be calling (you might also want to look a few lines around that line, in case it’s a multiline function call).

Now go back to the top of the error message and read the exact error in the error token (if you’re using a modern compiler, look for the one part of this error that’s highlighted in red). Read what this error is–you don’t necessarily have to read the types (which can be nearly impossible to understand), but there should be a short blurb before the types, like invalid operands to binary expression.

Now that you have an idea of where the error is in your code, and what the error is, browsing through the rest of the template errors may prove to be useful. Unfortunately, at this point, there is no longer a mechanical formula that can be used to debug–the fix will be up to your skill and knowledge–but having the above information before you start doing this is vital.

Here’s an example: in a few hundred lines of template output, only the text in the green and orange boxes are vital to troubleshooting the error. The green box tells me where the actual error is coming from (the other line numbers are fairly useless most of the time), and the orange boxes tell me what went wrong.

In this case, it looks like we’re trying to compare the equality of std::vector<int> and const int, which, of course, is a meaningless operation. Now the problem becomes to figure out why the program is trying to do this, and how to fix it.

Type errors
#

Coming soon!

Linker errors
#

Linker errors occur at the last stage of compilation, and are usually marked by a line saying undefined symbols to or multiple references to . However, they can also take on more exotic forms, like the missing vtable error.

The good news is that linker errors can almost always be resolved by taking one of three actions:

  1. Add the missing function/variable/code

    If you recognize the missing entity as one that belongs to you (e.g. a function that you wrote), the solution is to make sure it’s being compiled and linked, or to make sure you didn’t accidentally forget to write that code.

  2. Delete the duplicate function/variable/code

    If you have duplicate symbols, the easy solution is to delete some of them. Sometimes, this can be caused by defining certain functions (non-class members and non-template functions) in a header file and then accidentally including that header in multiple places.

    If you seem to be getting multiple definitions inside a header file, move all non-template definitions (both class and function) to a non-header file, and recompile. 9 times out of 10, this will fix the duplicate symbol error.

  3. Link the missing library

    If you don’t recognize the missing symbol as yours, it might belong to an external library that you forgot to link. The simplest way to do this is to go on Google and ask which library provides the symbol, then link that library into your build via the appropriate flags.

Since the linker gives you very little information to go off of, sometimes it can be difficult to work out where exactly the issue is occurring. Unfortunately, with how primitive most linkers are, and how much information has been stripped out of the code by the time we get to the linking stage, it is often a little bit of hocus pocus to figure out exactly what went wrong.

Run-time errors
#

Wrong values
#

Coming soon!

Obviously garbage values
#

Coming soon!

Segmentation Fault
#

Coming soon!