University of Leeds

Debug vs. release

Introduction

There are typically two configurations of software projects that are used at different stages of development. During the development stage, that is writing and testing the code, then the project usually has a debug configuration. This means that debug information is included in the executable (using the -g compile flag, covered later in the course) and tests may be run. When the project is deemed finished, it will be configured for release. This means the debug information will not be included, tests will not be run and certain optimisations may be done (e.g. using the -O2 flag) to reduce the size of the executable or minimise memory usage.

We will now briefly look at how to easily 'switch off' the tests when we do not want to run them.

Define pro-processor

When running the tests, we can just call the run_sum_tests() function.

1
2
3
4
int main() {
// test the function
  run_sum_tests();
}

Imagine we have finished the development stage and are ready to release the project. We can then go back through all our source files and delete or comment out lines similar to this and then re-compile. Sure, for our trivial example, this is easy. But what about projects with 100 million lines of code?

It turns out we can do it very easily using the define pre-processor and wrapping our testing functions with code like this.

1
2
3
4
5
6
int main() {
// test the function
#ifdef DEBUG
  run_sum_tests();
#endif
}

This basically means that if DEBUG is defined somewhere, then include the function call. If DEBUG is not defined, then it will not be included. We have seen previously that we can define things using the #define pre-processor macro in our source code. We can also do this when compiling using the -D flag. Using the following compile command will define DEBUG and mean that the tests are included.

g++ -std=c++11 -Wall -D DEBUG -o main.exe main.cpp

If we do not wish to include the tests (i.e. for release) you would just compile like so.

g++ -std=c++11 -Wall -o main.exe main.cpp

A note on 'de-bugging'

Running tests on your code will undoubtedly flag up errors that will need fixing. This is completely normal and something that even professional software engineers deal with on a daily basis. Just think of all the software updates released by Apple and Microsoft etc. These are to fix errors and mistakes made by their software engineers!

It is tempting to call these errors 'bugs'. However, this can give the impression that it is somehow not your fault and it is just an unlucky occurrence. Wrong! If YOUR code does not work as expected, it is because YOU have made a mistake and it is YOUR responsibility to find and fix it!

'De-bugging' is just as big a part of software development as is writing the code itself. If you have made a mistake and your first instinct is to put your hand up and expect the teacher or lab helper to find and fix it for you, you will never learn how to 'de-bug' and by extension, never learn how to program!

I have seen this first-hand with many students over many years. The students who graduate and still cannot program are usually the ones who ask for help every 15 minutes in the lab sessions. It is the same every lab session, in every module, in every year of study. Why is it that they get more one-to-one support and help then others but still need more help 15 minutes later? It is because they have never learned how to 'de-bug' as they have always relied on someone else to do it for them!

'De-bugging' can be frustrating and painful. Trust me, I have spent months of my life finding and fixing errors in code I have written! Although at the time it may seem like a waste of time, it is crucial when it comes to building experience and learning from your mistakes. It takes patience, determination and resilience. These are inherent parts of your personality that a teacher cannot give you!