marp | math | theme | footer |
---|---|---|---|
true |
katex |
custom-theme |
- What other compilation flags exist
- What compilation flags to use
- How to debug code
📺 Watch the related YouTube video!
- 🎨 - Style recommendation
- 🎓 - Software design recommendation
- 😱 - Not a good practice! Avoid in real life!
- ✅ - Good practice!
- ❌ - Whatever is marked with this is wrong
- 🚨 - Alert! Important information!
- 💡 - Hint or a useful exercise
- 🔼1️⃣7️⃣ - Holds for this version of C++(here,
17
) and above - 🔽1️⃣1️⃣ - Holds for versions until this one C++(here,
11
)
Style (🎨) and software design (🎓) recommendations mostly come from Google Style Sheet and the CppCoreGuidelines
- Lots of flags can be passed while compiling the code
- We have seen some already:
-std=c++17
,-o
, etc.c++ -std=c++17 -o test test.cpp
- ✅ Enable most warnings, treat them as errors:
-Wall
,-Wextra
,-Wpedantic
,-Werror
- Other warnings possible too:
-Wimplicit-fallthrough
,-Wsign-conversion
, etc. - Optimization options:
-O0
- no optimization[default]
-O3
- full optimization[preferred]
- Keep debugging symbols:
-g
(usually used with-O0
)
- Debugging will take more time than writing your code
- 💡 Read about how to think about debugging (really, do it!)
- When it comes to tools used for debugging,
there are largely two different philosophies:
- Using print statements
[my preference]
- Using a debugger
- Using print statements
- Each has advantages and disadvantages
- No debugging methods is complete without you thinking about the probable cause of the problem
- You can read a discussion on Hacker News about it
- Just add any printout statements to your code
- I usually use a form of a print statement shown below:
cerr << __FILE__ << ":" << __LINE__ << ": " << value << endl;
- This will print the filename and a line where its called
- We can also print a
value
of interest at any point - Usually requires to recompile only part of the program
- Typical workflow:
- Observe the behavior
- Form a hypothesis of what is wrong
- Try a fix and repeat until problem is solved
- This workflow forces us to understand the problem before rushing into trying a solution
- Allows stopping a program at a point and looking around
- Requires debug symbols (
-g
flag), needs full recompilation - Might be confusing with optimizations enabled
- Best program to use is probably
lldb
orgdb
- Insanely popular and powerful (and already installed 😉)
- Allows to print the backtrace
- No built-in gui 😢
- There are some tools built on top of GDB to fix this:
gdbgui
is a Python tool that provides a web GUI for GDB- VSCode C++ extension provides a GUI for the debugger
- I rarely use a debugger and when I do I use
lldb
/gdb
❌ Beware it has an error!
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3};
for (auto i = numbers.size() - 1UL; i >= 0; --i) {
std::cout << numbers[i] << std::endl;
}
return 0;
}
Once we run the program it crashes at some point:
[1] 74786 segmentation fault ./program
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3};
int count{}; // <- Count used for debugging
for (auto i = numbers.size() - 1UL; i >= 0; --i) {
std::cerr << "i = " << i << std::endl; // <- Debug print
std::cout << numbers[i] << std::endl;
if (count++ > 10) {break;} // <- Early exit
}
return 0;
}
- We can see smth like this on
stderr
:i = 2 i = 1 i = 0 i = 18446744073709551615
- Now we can guess what happens, here is a hint 😉
- Recompile the code with
-g -O0
flags - Start the code in the debugger:
λ › lldb ./program (lldb) target create "./program" Current executable set to '/private/tmp/program' (arm64). (lldb) r
- When it fails,
lldb
shows us where it fails - To find out why we will add a breakpoint
(lldb) breakpoint set --file program.cpp --line 6
- Restart by typing
r
, the execution will stop at breakpoint - We now add a
watch
on the variablei
(lldb) watch set var i
- Repeatedly enter
c
and press ⏎ until the issue is found - Full tutorial directly from
lldb