Debugging » History » Version 3
Ole Hansen, 08/27/2022 12:44 PM
1 | 1 | Ole Hansen | h1. Debugging |
---|---|---|---|
2 | 2 | Ole Hansen | |
3 | 3 | Ole Hansen | Advanced users may be interested in running the analyzer under a debugger. This is usually the fastest way to track down mysterious unexpected behavior or program crashes, certainly faster than adding print statements to the code and going through repeated edit-compile-run cycles. Jump to [[Debugging#Debug Sessions|Debug Sessions]] below to see an example. |
4 | |||
5 | h2. Debug Build |
||
6 | |||
7 | By default, the analyzer is built with debug symbols (CMake build type <code>RelWithDebInfo</code>) so that one can run the debugger right away without rebulding anything. That said, because of compiler optimizations, the debugger will sometimes appear to show the wrong program flow, some variables may not be available for inspection, etc. For the best debugging results, it may therefore be helpful to create a dedicated debug build. To do so, build the analyzer with the CMake build type "Debug": |
||
8 | 1 | Ole Hansen | <pre> |
9 | 3 | Ole Hansen | % cmake -B build-debug -S . -DCMAKE_BUILD_TYPE=Debug |
10 | % cmake --build build-debug -j |
||
11 | 1 | Ole Hansen | </pre> |
12 | 3 | Ole Hansen | You might also want to link against a debug version of ROOT or install an appropriate debuginfo package (e.g. <code>root-debuginfo</code> on RedHat systems using EPEL). A true debug version of ROOT requires "building ROOT from source":https://root.cern/building-root, again using <code>CMAKE_BUILD_TYPE=Debug</code>, which is beyond the scope of this document. |
13 | 2 | Ole Hansen | |
14 | 3 | Ole Hansen | Also, on RedHat Linux be sure to install <code>glibc-debuginfo</code>, <code>glibc-debuginfo-common</code>, and <code>libstdc++-debuginfo</code> to get debug support for STL classes and other standard library features. One Debian/Ubuntu systems, the corresponding packages are <code>libc6-dbg</code> and <code>libstdc++6-N-dbg</code>, where <code>N</code> should be replaced with the version of the <code>gcc</code> in use. Package names and availability may vary between different Linux versions. These steps are not necessary on macOS, where the relevant bundles come with the required symbol tables included. |
15 | 2 | Ole Hansen | |
16 | 3 | Ole Hansen | h2. Debug Sessions |
17 | |||
18 | The recommended debugger is <code>gdb</code> on Linux and <code>lldb</code> on macOS. To avoid problems with macOS's System Integrity Protection when using lldb, it may be helpful to not use /usr/bin/lldb directly, but instead create an alias to the command-line tools version, which isn't a specially-protected executable: |
||
19 | 2 | Ole Hansen | <pre> |
20 | 3 | Ole Hansen | % alias lldb='/Library/Developer/CommandLineTools/usr/bin/lldb' |
21 | 2 | Ole Hansen | </pre> |
22 | The analyzer may be run directly from the build location under the debugger of your choice: |
||
23 | <pre> |
||
24 | % ./build-debug/apps/analyzer |
||
25 | </pre> |
||
26 | 3 | Ole Hansen | Once the analyzer is running, open a second terminal and find out the PID of this analyzer process. Then "attach" the debugger, which will stop the analzyer and allow you to configure the session, e.g. to set break points, etc. For example, on Linux using <code>gdb</code>: |
27 | 2 | Ole Hansen | <pre> |
28 | % ps a | grep analyzer |
||
29 | 13643 pts/3 S+ 0:00 ./build-debug/apps/analyzer |
||
30 | % gdb |
||
31 | GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 |
||
32 | 1 | Ole Hansen | ... |
33 | 2 | Ole Hansen | (gdb) attach 13643 |
34 | ... |
||
35 | (gdb) break THaRun::THaRun |
||
36 | Breakpoint 1 at 0x7fab342a10a7: THaRun::THaRun. (3 locations) |
||
37 | (gdb) continue |
||
38 | Continuing. |
||
39 | </pre> |
||
40 | This sets a breakpoint for all versions of the <code>THaRun</code> constructor. The <code>continue</code> command (shorthand <code>c</code>) resumes execution of the program. |
||
41 | |||
42 | 3 | Ole Hansen | Go back to the analyzer prompt and create a <code>THaRun</code> object. The process will stop and print information (in the debugger window), allowing you to inspect data, step through the code, etc.: |
43 | 2 | Ole Hansen | <pre> |
44 | analyzer [0] r = new THaRun("/data/raw/run_7211.evio.0") |
||
45 | </pre> |
||
46 | In the debugger window, you'll see |
||
47 | <pre> |
||
48 | 1 | Ole Hansen | Breakpoint 1, THaRun::THaRun (this=0x503bb20, |
49 | 2 | Ole Hansen | fname=0x7fab188f002c "/data/raw/run_7211.evio.0", |
50 | description=0x7fab188f004f "") |
||
51 | at /home/ole/Develop/analyzer/Podd/THaRun.cxx:39 |
||
52 | 39 fSegment(-1), fStream(-1) |
||
53 | (gdb) p fname |
||
54 | $1 = 0x7fab188f002c "/data/raw/run_7211.evio.0" |
||
55 | (gdb) |
||
56 | </pre> |
||
57 | Here, we printed (shorthand <code>p</code>) the contents of the variable <code>fname</code>. To end the session, type <code>q</code> in the debugger window. |
||
58 | 1 | Ole Hansen | |
59 | 3 | Ole Hansen | The process is very similar under macOS with <code>lldb</code>, although the syntax of some <code>lldb</code> commands differs from that of <code>gdb</code>. You can find side-by-side comparisons of <code>gdb/lldb</code> commands online. Obviously, this only scratches the surface of what is possible with a debugger. If you are unfamiliar with <code>gdb</code> or <code>lldb</code>, there are plenty of tutorials available online that should get you started quickly. |