Address and Leak Sanitizers for C++

You heard that in C++ there’s always the risk to leak memory, and now you’re wondering if there is a tool that can help you find if your program contains memory leaks? Luckily, there are some tools, such as the LeakSanitizer.

First of all, this is something done at runtime – this sort of functionality won’t be able to find your memory leaks at build time, unfortunately. You can use the AddressSanitizer to help you find memory errors, which might include things that lead to memory leaks, but the leak sanitizer is explicitly made for finding memory leaked at runtime.

Now, even though it’s a runtime functionality, you will still need to tell your compiler to activate the sanitizer at build time. There are several options to do so.

As I follow a lot the cpp-best-practices/gui_starter_template, I take advantage of the ENABLE_DEVELOPER_MODE CMake variable that will instruct project_options to enable sanitizers for me. However, all you need in theory is really just to set the flag “-fsanitize=address” at compilation time – beware that Apple Clang, as of version 14.0.0, does not support yet this sanitizer (you’ll need clang or gcc, take a look here to see how to install them).

Finally, as this is a runtime option, and you will need to set a variable to tell the sanitizer that you want to use a specific feature, in this case the “detect_leaks=1“. In order to do so, you’ll need to set the LSAN_OPTIONS before executing your program, e.g.,

LSAN_OPTIONS="detect_leaks=1" ./bin/app

At the end of the program, the leak detector will give you some warnings if there were memory leaks found.

Note: In CLion, you can set sanitizer flags in Preferences | Build, Execution, Deployment | Dynamic Analysis Tools | Sanitizers.

Now, when you run the program in the IDE, the variable will be set, and at the end of the program, you will get some feedback if some memory leaks were found.

How to install Qt6 for C++ on Mac

Lately I have been working on a hobby project written in C++ and Qt6.

Had I not ditched Conan to use Vcpkg, due to their backward incompatible migration from v1 to v2 which completely wasted my build, probably this would post wouldn’t exist. 🙂

Anyway, I stumbled upon a quite nasty issue that seems to hit some people using Qt, probably because of the way it is installed.

In fact, after using Conan, I decided to use homebrew to install qt, and the behavior is, to say the least, weird.

When you build your project with cmake and package it as an OSX Bundle like in the code:

if (APPLE)
    add_executable(myapp MACOSX_BUNDLE)
# ...
endif()

Then you get an issue like:

 

objc[97951]: Class RunLoopModeTracker is implemented in both /usr/local/Cellar/qt/6.3.2/lib/QtCore.framework/Versions/A/QtCore (0x10d0626c8) and /Users/path/to/myapp/build/bin/myapp.app/Contents/Frameworks/QtCore.framework/Versions/A/QtCore (0x11d0ca6c8). One of the two will be used. Which one is undefined.QObject::moveToThread: Current thread (0x6020000024f0) is not the object's thread (0x60200000e910).

Cannot move to target thread (0x6020000024f0)

You might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.qt.qpa.plugin: Could not load the Qt platform plugin "cocoa" in "" even though it was found.This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

However, if you use macdeployqt, the issue disappears. This, though, means you automagically lose the ability to use the “Run in IDE” functionality, because it just doesn’t work.

The weird thing is that after the build (and before using macdeployqt) the package folder contains lots of libraries, including the cocoa plugin it apparently fails to find, the Qt dependencies you need and also the ones you don’t need (e.g., I don’t use QtNetwork, but it also appears in the directory). Therefore, at least from the look of it, everything should be there in the folder, and there shouldn’t be any need for loading things from outside.

Finally, after hours of useless debugging, trying to understand which library or plug-in was causing the double loading, I decided to find another way to install Qt.

I chose aqtinstall, the tool behind the Github Action to install Qt in the CI environment – which I use on Github already. Nonetheless, the method applies to any machine, so why not.

With a couple of simple commands:

$ mkdir qt6
$ cd qt6
$ aqt install-qt mac desktop 6.3.2 clang_64

At this point, you need to set the environment variables so that when you run CMake, the qt libs are found correctly. I recommend creating a simple file, e.g., ~/setup-qt.sh, so that you can load it also from your IDE (e.g., in CLion you can load an environment file in Preferences | Build, Execution, Deployment | Toolchains).

$ export Qt6_DIR=/path/to/qt6/6.3.2/macos/
$ export QT_PLUGIN_PATH=/path/to/qt6/6.3.2/macos/plugins
$ export PKG_CONFIG_PATH=/path/to/qt6/6.3.2/macos/lib/pkgconfig
$ export QML2_IMPORT_PATH=/path/to/qt6/6.3.2/macos/qml
$ export PATH="/path/to/qt6/6.3.2/macos/bin:$PATH"

Now, you should finally have an environment that works like a charm – without having to rely on the deployment tool.