Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
Valgrind: possible memory-leak when setting up connections
I am trying to check my code for possible memory leaks using valgrind in Qt-Creator.
Valgrind reports like 500 issues, however only 3 are shown in the output-window when the filter "External Errors" is disabled.
Am I right to assume that those external errors (if they are real errors and not false-positives) are caused by external libraries which are included and used by Qt itself, so that I better just ignore them?
There are possible leaks reported when i setup some connections.
My original post was way longer containing code snippets showing what class inherits from what and how my program is structured. However, that would make this post multiple pages long, so I've removed it and just copied the valgrind message.
I know that it is probably to impossible solve the issue with the low amount of data that I am providing here, however I hope that it's a newbie-problem and maybe someone knows the answer right away.
When I find some time later the week and no solution was found, I will try to make a small program replicating the error which i can post here. If someone has got the time and muse, the code is in my repository which I've set to public: Qt_BTLE_Mooshi
The issue itself:
connect(rp_data_, &DataDevice::SigControllerConnected, this, &StateConnectToController::SlotControllerConnected);
rp_data_ is a reference of a QPointer containing an instance of the class with the signal, the slot is part of the class where the connection is made. The connection is created in the constructor of the class, maybe that is relevant here.
The error-message says:
160 bytes in 1 blocks are possibly lost in loss record 11,020 of 12,253
in StateOperating::StateOperating(StatemachineDevice&, QState*) in Documents/Git/Qt_BTLE_Mooshi/Device/StateDevice.cpp:31
1: malloc in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so
2: QObjectPrivate::addConnection(int, QObjectPrivate::Connection*) in /Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
3: QObjectPrivate::connectImpl(QObject const*, int, QObject const*, void*, QtPrivate::QSlotObjectBase, Qt::ConnectionType, int const*, QMetaObject const*) in /Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
4: QObject::connectImpl(QObject const*, void*, QObject const, void*, QtPrivate::QSlotObjectBase, Qt::ConnectionType, int const*, QMetaObject const*) in /Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
5: QMetaObject::Connection QObject::connect<void (DataDevice::)(), void (StateOperating::)()>(QtPrivate::FunctionPointer<void (DataDevice::)()>::Object const, void (DataDevice::)(), QtPrivate::FunctionPointer<void (StateOperating::)()>::Object const*, void (StateOperating::)(), Qt::ConnectionType) in /Qt/5.15.0/gcc_64/include/QtCore/qobject.h:268
6: StateOperating::StateOperating(StatemachineDevice&, QState) in /Documents/Git/Qt_BTLE_Mooshi/Device/StateDevice.cpp:31
7: States::States(StatemachineDevice&) in /Documents/Git/Qt_BTLE_Mooshi/Device/StateDevice.cpp:588
8: StatemachineDevice::StatemachineDevice(QBluetoothAddress const&, QObject*) in /Documents/Git/Qt_BTLE_Mooshi/Device/StatemachineDevice.cpp:7
9: DeviceHandler::ConnectToDevice(QBluetoothAddress const&) in /Documents/Git/Qt_BTLE_Mooshi/DeviceHandler.cpp:30
10: MainWindow::on_DeviceList_itemDoubleClicked(QListWidgetItem*) in /Documents/Git/Qt_BTLE_Mooshi/mainwindow.cpp:164
11: MainWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in /Documents/Git/build-Qt_BTLE_Mooshi-Desktop_Qt_5_15_0_GCC_64bit-Debug/moc_mainwindow.cpp:83
12: MainWindow::qt_metacall(QMetaObject::Call, int, void**) in /Documents/Git/build-Qt_BTLE_Mooshi-Desktop_Qt_5_15_0_GCC_64bit-Debug/moc_mainwindow.cpp:120
13: void doActivate<false>(QObject*, int, void**) in/Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
14: QListWidget::itemDoubleClicked(QListWidgetItem*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
15: void doActivate<false>(QObject*, int, void**) in /Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
16: QAbstractItemView::doubleClicked(QModelIndex const&) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
17: QAbstractItemView::mouseDoubleClickEvent(QMouseEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
18: QWidget::event(QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
19: QFrame::event(QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
20: QAbstractItemView::viewportEvent(QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
21: QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
22: QApplicationPrivate::notify_helper(QObject*, QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
23: QApplication::notify(QObject*, QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
24: QCoreApplication::notifyInternal2(QObject*, QEvent*) in /Qt/5.15.0/gcc_64/lib/libQt5Core.so.5.15.0
25: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) in /Qt/5.15.0/gcc_64/lib/libQt5Widgets.so.5.15.0
So what's at this line?
I think you can't fix it and it's Qt internal. As long as it's only 1 block it's not really a leak which should worry you.
/edit: you leak DataDevice
Oh! Thats definitely a leak, i forgot to pass the parent object to the QObject in the initializer-list.
Fixed that, thanks. Should now be on github, too.
The leaks are still detected, though :(
So you think I should just go with it?
I've spend already multiple days looking for a solution and hints on the internet, guess i really have to move on - it's just that those tiny details drive me nuts.
So you think I should just go with it?
yes, as long as it's only 1 block - so the 'leak' only occurs one time it's fine. It can e.g. an initialization of a Qt internal memory block which is needed for connections and is never deallocated since it's needed until the very end of the program.
@Christian-Ehrlicher The thing is, I intended to call this 'driver' multiple times, maybe even many thousand times in the lifetime of the program.
Like 48 times a day per device, multiple devices, and the program is running in endless mode.
Do you know if there is way to see the total memory consumption of a program? So that I can create and delete the statemachine like 10000 times and see if the memory size is rising?
So when you call it multiple times and only one block leaks my explanation is correct, or? It's a one-and-only allocation.
unzu last edited by unzu
I don't think so, maybe I'm getting this wrong, but everytime I create a new instance of my statemachine it creates those connections inside which maybe cause leaking?
which maybe cause leaking?
Again: valgrind only shows "160 bytes in 1 blocks" - no matter how often you call it, so how do you think it will leak every time you call it?
Sorry, I probably don't understand what's really happening here. I thought that whenever I create an instance of the statemachine there is some memory allocated which is not freed on deletion of the statemachine, so that for every instance there is some lost memory until I stop the application or run out of memory.
Again, I'm no expert and just trying to build a small application that won't crash after x hours of usage..
I thought that whenever I create an instance of the statemachine there is some memory allocated which is not freed on deletion of the statemachine, so that for every instance there is some lost memory until I stop the application or run out of memory.
Then you would see more than one of such valgrind warning or more than one block allocation, or?
Ah I see - so if a leak would happen everytime I create a new instance of the object, the number of blocks would increase?
I compiled the project with Visual Studio because you can see the process-memory easily there.
After fixing another leak I found in one of the subclasses of the statemachine-class the process memory stayed steadily on ~13MB, even after creating and deleting more than 100.000 instances of the statemachine.
So i think (if there is really a leak) that it is, as you have suggest, once in the lifetime of the program.
I create a new instance of the object, the number of blocks would increase?
correct, therefore I suspect it's some static memory internally needed for the signal/slot handling and can be ignored. You just have to start worring about a 'leak' when it increases with the times you call a function. If it stays at a specific (small) amount it's fine. Esp. when the amount is 1 :)