Coder Tools

From GnuCash
Revision as of 02:58, 4 June 2024 by Jralls (talk | contribs) (Add address sanitizer and coverage build options.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Sometimes somebody finds a tool, which is better than standard tools. Here we share our knowledge.


These are compiled-in instrumentation that crash the program and provide a stack trace for], leak, and a variety of behavior errors. It's easily enabled at build time for Unix and macOS by passing -DCMAKE_BUILD_TYPE=Asan to cmake; also pass -DLEAKS=ON to enable the leak sanitizer (leak sanitizer doesn't work on macOS) or -DODR=ON to detect one-definition rule violations. There's a CI workflow with build type Asan so all of the tests are checked at every commit.


A useful measure of a test program's effectiveness is how much of the code it exercises. That's measured by having the compiler instrument the program and then run the tests. That's also built into the GnuCash build system, see Coverage, and it's also a CI workflow that runs daily.

Memory Leaks


For C exist sysprof, hotspot, heaptrack (memory profiler), Valgrind,... Plenty of profiling tools. I have done some profiling with sysprof and heaptrack (never used valgrind). Both have interactive user interfaces to drill down on profiling data. I currently prefer heaptrack as it doesn't need special privileges. Last time I used sysprof (which has been a while) it needed admin privileges to run.

Using Valgrind with GnuCash

(This information was extracted from the Hacking file in the GnuCash source directory)

Note: tools like sysprof and hotspot mentioned above can be used directly without any source or build modifications. That makes them relatively easy to get started with.

On the other hand valgrind has been around for a very long time and people may prefer it over the "newer" siblings. So here are a few notes on how to use it. After building gnucash, run

$ ${prefix}/bin/gnucash-valgrind

However, I did not find valgrind to be useful. It reported a bunch of guile bugs, some g_hash_table bugs, and then the program exited prematurely for no apparent reason. :-(

For the moment, gnucash-valgrind uses the suppressions in


For valgrind-gnucash.supp, this comment was made (but is perhaps outdated by now ?): This file needs to be cleaned up in two ways:

  1. There are a bunch of duplicate suppressions in the file - the suppressions in place were auto-generated by valgrind itself [--gen-suppressions=yes], and it makes no effort to output the suppression only once.
  2. There are a bunch of suppressions which need to not be suppressions, but instead just not be generated by valgrind.

Using Callgrind with GnuCash

(As with valgrind, this snippet was extraced from the Hacking file in the GnuCash source directory.)

In order to debug with callgrind, you need to add a couple of code fragments around the section of code you are profiling. This is easiest if you can find the function that invokes the routine(s) you want to profile, add the following code around the function call of interest.

Add the following to the start of the file:

#include <valgrind/callgrind.h>

Add the following to the start of the calling function:

static GTimeVal start, end;

Add the following just before the function of interest:

g_print("Start timing.\n");

Add the following just after the function of interest:

if (start.tv_usec > end.tv_usec) {
  end.tv_usec += 1000000;
  end.tv_sec  -= 1;
g_print("Callgrind enabled for %d.%6d seconds.\n",
        (int)(end.tv_sec - start.tv_sec),
        (int)(end.tv_usec - start.tv_usec));

You will need to recompile, and then run the 'gnucash-valgrind' wrapper script instead of the normal 'gnucash' script.

Note Version 3.2 of valgrind has changed the above macros to no longer take an argument. In order to compile with this version of valgrind you will need to remove the trailing parentheses and semicolon.

Note Valgrind doesn't play well with macOS, but macOS has its own tools built into dyld. See dyld(1) for details.