From 9592f5206613f9395d843c31860c17d4e346281c Mon Sep 17 00:00:00 2001 From: Michael McLeod Date: Mon, 16 Feb 2026 14:50:29 +0000 Subject: [PATCH] Fix tooling notes --- 06tooling/StyleSafetyTooling.md | 104 +++++++++++++++++++++++++++++ 06tooling/index.md | 3 +- 06tooling/sec00TimingAndTooling.md | 62 +---------------- 3 files changed, 108 insertions(+), 61 deletions(-) create mode 100644 06tooling/StyleSafetyTooling.md diff --git a/06tooling/StyleSafetyTooling.md b/06tooling/StyleSafetyTooling.md new file mode 100644 index 000000000..ecea85124 --- /dev/null +++ b/06tooling/StyleSafetyTooling.md @@ -0,0 +1,104 @@ +--- +title: Tooling +--- + +# Tooling + +This week we will introduce a number of tools which are useful when developing and analysing C++ code. None of them are strictly necessary, but each serves a useful purpose and helps to detect or fix problems that can be difficult to find or keep on top of otherwise. + +If you are using the **Docker container** then you will not need to install any of these tools manually; the container will already have pre-installed valgrind, clang-tidy, and clang-format. However, if you do not wish to use Docker you can install these tools yourself. + +## Installation (only if not using Docker) + +**N.B.** Please remember that if you are using Windows for this course you will need to install these tools **inside WSL** (Windows Subsystem for Linux) rather than following a normal Windows installation. To do so, you can +1. Open a Command Prompt and type `wsl` to go into the WSL command line. From there you can follow Linux instructions for installing command line tools like Valgrind. +2. Open VSCode and [connect to WSL using the button in the bottom left hand corner](https://code.visualstudio.com/docs/remote/wsl). From there you can add extensions to VSCode, or open a terminal to access the WSL command line and install command line tools. + +### WSL / Linux + +On WSL/Linux you can install all three using the following commands in the terminal: + +``` +apt-get -y install --no-install-recommends valgrind clang-tidy clang-format +``` + +You may need to add `sudo` before these commands depending on the permissions on your system. If it does not find any of these tools you may need to update your packaged index using: + +``` +apt-get update +``` + +### MacOS + +If you want to use MacOS without using the devcontainer then the process is a little more involved. + +- Valgrind may not be compatible with your device depending on your OS and architecture. XCode command line tools however comes with a similar tool called `leaks` which you can use instead to detect memory leaks. +- Clang-format can be installed by using homebrew (`brew install clang-format`), but clang-tidy cannot. You can install both `clang-format` and `clang-tidy` as part of llvm (`brew install llvm`), but llvm is a large install, and you will have to then add these to your path. + +## Compiler warnings + +Even without any further tooling, your compiler can already provide a lot of really useful code analysis that can improve the quality of your code and catch various mistakes. For a detailed look at your compiler warning options you can take a look at the [g++ warning options documentation](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html). + +Compiler warnings can be turned on for `g++` by using some of the following flags: + +- `-Wall`: enables common warnings for things like functions with missing return statements, uninitialised variables, unused variables. Some less common (but extremely useful) warnings in this category include warnings for strict aliasing, dangling pointers/references, and array bounds (for arrays with static allocation), although these kinds of memory related checks are imperfect and cannot catch all cases of bad behaviour. +- `-Wextra`: enables some additional warnings that are less common such as unused function parameters. For some of these warnings to function correctly you will also need `-Wall` turned on. +- `-Wconversion`: enables warnings for implicit conversions that can alter values such as `double` to `float`, but not for sign conversions. +- `-Wsign-conversion`: enables warnings for implicit conversions between signed and unsigned types that may cause underflow/overflow errors. +- `-Werror`: turns all warnings into compilation errors so that the program will not compile until all the warnings are resolved. + +I would recommend using all of these flags by default, especially when checking things such as your coursework, although it is sometimes useful to turn off `-Werror` during development (for example, when you have a variable that is unused because you haven't got to the stage in an algorithm where it is going to be used, but you want to compile in the meantime). + +## Debugging inside VSCode + +You can use the debugger inside VSCode, or you can just `gdb` in the command line to debug your programs. We covered how to set up your debugger in the first week's class, so you can go back to that if you need a refresher. Microsoft also provides [this tutorial for setting up VSCode with cmake](https://code.visualstudio.com/docs/cpp/CMake-linux), which is a little more work to set up but can make it easier to integrate building and debugging into the VSCode environment. + +## Debugging memory issues with Valgrind (or `leaks`) + +We've discussed in the first half of this course many of the problems that can arise from improperly managed memory, including memory leaks and segmentation faults (which occur due to invalid memory accesses). Valgrind is a **memory profiler and debugger** which is extremely useful for analysing our programs memory usage by keeping track of allocations and deallocations (amongst other things). This can be vital for checking that we don't have memory leaks when we run our program. Memory leaks can be especially hard to spot, since they typically grow over time during a program's execution and only cause the program to abort if you run out of memory. This means that short programs such as tests rarely use up enough memory to make a leak obvious, only for the problem to cause a job on a computer cluster to fail after days of running because the memory has been exhausted. By detecting when memory is allocated and deallocated, valgrind can check if we have failed to free any memory _even in short test cases_. + +A limitation of valgrind is that it does _not_ guarantee that your program is free of problems; it only reports what happened _this time_ when you ran the program. If you have a memory leak that only happens under certain circumstances, it won't catch it unless it occurs during a run that you are analysing with valgrind. Nevertheless it is extremely useful, especially as + +Valgrind provides a [quick-start guide](https://valgrind.org/docs/manual/quick-start.html) which demonstrates how to run valgrind with a basic C++ program. It demonstrates the detection of a _heap block overrun_ (i.e. if we have written into invalid memory by going beyond the end of an array) and a _memory leak_ (a heap allocation that has not been freed). + +If you are using MacOS you can use `leaks` in a similar way. + +## Linting with clang-tidy + +**Linters** are tools that statically analyse code to find common bugs or unsafe practices; it is significantly more powerful than just using the g++ compiler warnings. Microsoft has provided a tutorial for setting up the `clang-tidy` tool with VSCode: + +{% include youtube_embed.html id="8RSxQ8sluG0" %} + +You can also just run clang-tidy from the command line: + +``` +clang-tidy main.cpp -- -std=c++17 +``` + +will provide the default analysis of a code file. You can see what checks clang-tidy does by default using: + +``` +clang-tidy -list-checks +``` + +## Formatting with VSCode or clang-format + +Formatters make sure that your program is presented with consistent style with respect to things like line length / line breaks, indentation, and spacing. These are vital for making sure that your code is easy to read and understand, and also makes sure that teams of programmers working together can construct a code base that is consistent in style. This has the added benefit in collaboration of making sure that changes to the code that need to be reviewed are not clogged by meaningless style changes when two people who can't agree on a coding style are working on the same pieces of code! + +In VSCode, if you have the C++ extension pack installed, you should be able to format your code using: + +- Highlight the code that you want to format or use ctrl-A to highlight all, then ctrl-K followed by ctrl-F to format it. + +You can also use a tool called `clang-format` to format code from the terminal, and there is a `clang-format` VSCode extension as well. There is a [clang-format guide](https://clang.llvm.org/docs/ClangFormat.html) for getting started using it if you want to integrate it into projects. + +The simplest start is to just run `clang-format` from the command line. If you run it with no flags, it will simply write the result to the terminal. You can use the `-i` flag (for "in place") to have clang-format modify your source files directly. For example: + +``` +clang-format -i main.cpp +``` + +Formatters are typically configurable, and `clang-format` provides a number of different presets based on [common style guides](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#basedonstyle); for our purposes it's not very important which one of these that you use provided that you are consistent and your code is clearly presented. + + + + diff --git a/06tooling/index.md b/06tooling/index.md index b5dbe2016..2985605f7 100644 --- a/06tooling/index.md +++ b/06tooling/index.md @@ -6,7 +6,8 @@ This week we'll learn about some of the tools that we can use to improve our cod You should look over and install the following tools, and familiarise yourself a little with the timing statements available in C++. -1. [Timing and Tooling](sec00TimingAndTooling.html) +1. [Timing](sec00TimingAndTooling.html) +2. [Tooling](StyleSafetyTooling.html) ## Why use Libraries? diff --git a/06tooling/sec00TimingAndTooling.md b/06tooling/sec00TimingAndTooling.md index df69fcd00..ebb6d2cd1 100644 --- a/06tooling/sec00TimingAndTooling.md +++ b/06tooling/sec00TimingAndTooling.md @@ -1,10 +1,8 @@ --- -title: Timing and Tooling +title: Timing --- -This week we'll look a bit at how to time our code for performance, and also introduce a number of tools which we can use to develop and improve our code. We'll start using these in the practical but please make sure you install and set up the tools ahead of time, and reach out to us before class if you have trouble doing so. - -## Timing +# Timing Timing statments can be inserted into the code usind the `` header from the standard library. @@ -87,60 +85,4 @@ int main() - We showed above that we _can_ convert to microseconds and so on, but we don't have to do so, we can work directly with `nanoseconds` if that's useful. - It can also be a good idea to just wrap up some timing code in a little class so you can reuse it across projects and don't have to keep thinking about all this stuff. -## Tooling - -**N.B.** Please remember that if you are using Windows for this course you will need to install these tools **inside WSL** (Windows Subsystem for Linux) rather than following a normal Windows installation. To do so, you can -1. Open a Command Prompt and type `wsl` to go into the WSL command line. From there you can follow Linux instructions for installing command line tools like Valgrind. -2. Open VSCode and [connect to WSL using the button in the bottom left hand corner](https://code.visualstudio.com/docs/remote/wsl). From there you can add extensions to VSCode, or open a terminal to access the WSL command line and install command line tools. - -## Debugging inside VSCode - -We can debug our code from inside VSCode but it requires a little setup to make sure we're correctly using CMake when debugging. Follow [this tutorial to set up your VSCode properly with CMake](https://code.visualstudio.com/docs/cpp/CMake-linux). - -## Debugging memory issues with Valgrind - -If you're unlucky enough to have to resort to unsafe memory management with raw pointers, you will almost certainly meet a **segmentation fault** or segfault, if your program tries to access memory it doesn't strictly have access to. This can happen due to many different types of bugs; stack overflows, freeing already freed pointers, off-by-one bugs in loops, etc, but can be notoriously tricky to debug. - -Valgrind is a **memory profiler and debugger** which can do many useful things involving memory but we just want to introduce its ability to find and diagnose segfaults by tracking memory allocations, deallocations and accesses. - -You should follow [Valgrind's Quickstart Guide](https://valgrind.org/docs/manual/quick-start.html). - -## Linting with clang-tidy - -**Linters** are tools that statically analyse code to find common bugs or unsafe practices. We'll be playing with the linter from the Clang toolset, `clang-tidy` so follow this tutorial on setting up clang-tidy with VSCode: - -{% include youtube_embed.html id="8RSxQ8sluG0" %} - -## Formatting with clang-format - -If you've done much Python programming you probably already know the power of good formatters, tools that reformat your code to a specification. This can help standardise code style across codebases and avoid horrid debates about spaces vs tabs, where curly braces should go, or how many new lines should separate functions. - -Again, we'll be peeking into the Clang toolbox and using `clang-format` to automatically format our code. Follow [this guide on setting up a basic .clang-format file](https://leimao.github.io/blog/Clang-Format-Quick-Tutorial/) and see clang-format's [list of common style guides](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#basedonstyle) for more information about what styles are available. Look at a few, choose one you like and use that style to format your assignment code. - -You can also use [the clang-format VSCode extension](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) to automatically format your code on saving. - -## Compiler warnings - -One of the easiest ways to improve your code is to turn on **compiler warnings** and fix each warning. Some companies even require that all compiler warnings are fixed before allowing code to be put into production. Check out [this blog post on Managing Compiler Warnings with CMake](https://www.foonathan.net/2018/10/cmake-warnings/) for details on how to do this in our CMake projects. I recommend you use these warnings to fix potential bugs in your assignment. - -## Optional: Performance profiling with gprof - -Although you won't be required to use one on this course, as we move towards *performant* C++, one useful tool is a **profiler**. This is a tool that runs your code and measures the time taken in each function. This can be a powerful way to understand which parts of your code need optimising. - -There are many advanced profilers out there but a good, simple profiler is `gprof`. This also has the advantage of coming with most Linux distributions, so is automatically available with Ubuntu on either a native Linux machine or WSL. - -You can watch this introductory video on using gprof: - -{% include youtube_embed.html id="zbTtVW64R_I" %} - -and try profiling one of your own codes. Since we're using cmake, we can't directly add the required `-pg` flags to the compiler so we'll have to tell cmake to add those flags with: - -``` -cmake -DCMAKE_CXX_FLAGS=-pg -DCMAKE_EXE_LINKER_FLAGS=-pg -DCMAKE_SHARED_LINKER_FLAGS=-pg ... -``` - -On MacOS you can try using Google's [gperftools](https://github.com/gperftools/gperftools) which is available through homebrew. - -- You should target the areas of your code where your application spends the most time for optimisation. -- Profilers are excellent for identifying general behaviour and bottlenecks, but you may be able to get more accurate results for specific functions or code fragments by inserting timing code.