Nicolas Fella wrote a bit about enabling memory leak detection in KDE CI, and I thought I’d add some comments from a different software engineering environment (e.g. my work-work).

Guidelines for Memory Management

At work-work, we have a slightly peculiar software environment:

  • Bleeding edge C++ use – C++23 if possible, 26 features being experimented-with – and a strong reliance on C++ language and library features. Use C++ containers, std::string (with an *implicit “here be UTF-8-encoded strings”), std::jthread, business-logic in standard C++ wherever possible.
  • Qt 5.6.3, from 2017, for UI code. That’s pre-C++17.

This leads to two guidelines about memory-management in our application:

  • Use Qt’s memory model and ownership only for QWidget’s inheritance tree,
  • .. well, ok, incidentally for things inheriting from QObject.
  • Use C++ resource management for all other memory-management.

This does mean that depending on where in the codebase you’re working, you either have to be a “C++ purist” (as Nico puts it) or a “Qt pragmatist” (as I’ll phrase it). Note that the guideline is not “use smart pointers”, because that last guideline can deconstructed a little (it wouldn’t surprise me if this was inspired by Klaus Iglberger):

  • If a class manages a resource, then that resource-management should be the only thing it does,
  • If an object needs resources, then those resources should be members (sub-objects) of a class as above.

Often that means that memory-management is in the hands of std::unique_ptr, but std::vector does the job also. We have a handful of other classes for resource-management as well, like a wrapper for FILE * for those places where we need to interact with C’s stdio library. Granted, FILE * is probably not a source of memory-leaks, but it is a managed resource, and forgetting one will lead to leaking file-descriptors in the long run.

Leaky Libraries

Dealing with memory leaks can be difficult particularly when they happen in libraries not under your control. As an example, I wrote this program ( headers elided for brevity) which is a Qt5 program:

int main(int argc, char **argv)
{
  QApplication a(argc, argv);
  QTimer::singleShot(5000, qApp, &QApplication::quit);
  return a.exec();
}

This is, like, the simplest Qt5 program. It sits there for five seconds and then quits. It also leaks 1662 bytes of memory, in 19 allocations, according to my ASAN output. They leak from allocations done in libQt5Core. Adding a QLabel and displaying some text adds leaks in libfontconfig, and the leaks keep accumulating as more libraries enter the mix.

Granted, none of these leaks are large. I’m not even sure that they are impolite, but they’re there and it makes tracking down leaks in my code harder, because there’s some baseline of leakage that I need to ignore. Filtering out the noise becomes a serious undertaking.

Takeaway

Chasing all the memory-leaks is hard. Chasing any leaks in KDE Frameworks is something I can only applaud.