False positive on clang static analysis when using Qt memory management

769 Views Asked by At

Considering the following code:

#include <iostream>
#include <QObject>

class ParentClass : public QObject
{
public:
  explicit ParentClass(QObject *parent = nullptr) : QObject(parent) {
    std::cout << "ParentClass" << std::endl;
  }
  ~ParentClass() override {
    std::cout << "~ParentClass" << std::endl;
  }
};

class ChildClass : public QObject
{
public:
  explicit ChildClass(QObject *parent = nullptr) : QObject(parent) {
    std::cout << "ChildClass" << std::endl;
  }
  ~ChildClass() override {
    std::cout << "~ChildClass" << std::endl;
  }
  void hi() { std::cout << "hi" << std::endl; }
};

int main()
{
  auto *parent = new ParentClass();
  auto *child = new ChildClass(parent);
  child->hi();
  delete parent;

  return 0;
}

When I run clang static analysis (scan-build), it reports a potential memory leak:

main.cxx:34:3: warning: Potential leak of memory pointed to by 'child'
  delete parent;
  ^~~~~~~~~~~~~
1 warning generated.

The issue is I am using Qt's memory management here, where the parent object on a tree structure manages the children. It works perfectly fine, as can be seen by the output:

ParentClass
ChildClass
hi
~ParentClass
~ChildClass

I can see that this is not obvious, but on the other hand I have a lot of code using Qt infrastructure, hence a big report full of false-positives.

The FAQ (https://clang-analyzer.llvm.org/faq.html) doesn't talk about memory leaks.

Is there a way to suppress these false-positives so they won't be reported?

All I could think of is to create some pretend code calling delete, but it would require changing a lot of code. And besides, it feels like a hack:

  auto *parent = new ParentClass();
  auto *child = new ChildClass(parent);
  child->hi();
#ifdef __clang_analyzer__
  delete child;
#endif
  delete parent;

Is there a better way?

1

There are 1 best solutions below

0
On

This is what I do to solve these warnings:

in my_utils.h:

// For avoiding memory leak warnings
#define IGNORE_MEMORY_LEAK_WARNING(x) no_memory_leak_ptr = x 
extern void *no_memory_leak_ptr;

in my_utils.cpp:

// For avoiding memory leak warnings
void *no_memory_leak_ptr;

Then, in the code with the warning, I can just do something like:

HelpWindow *win = new HelpWindow(this, HelpWindow::HelpAbout);
IGNORE_MEMORY_LEAK_WARNING(win);

For me, this is very tidy. And using #defines alloows me to change the method later if a better solution comes around.