PDA

View Full Version : Qt Plugins causing memory problems?



gavinmagnus
2nd August 2017, 15:51
Architecture of my project looks as follows:

Main project, that is compiled as stand-alone application:

TEMPLATE = app


Sub projects, that are compiled as libraries:

TEMPLATE = lib


Plugins, that are compiled as Qt Plugins:

CONFIG += plugin
TEMPLATE = lib


Common directory, that contains libs used by more than one element, f.e. all sub projects and one plugin.

TEMPLATE = lib
---
Main project accesses Sub projects as a libraries:

INCLUDEPATH += \

$$(SUB)/my_sub_pro1/lib \




DEPENDPATH += \

$$(SUB)/my_sub_pro1/lib \




LIBS += \

-L$$(BUILD_SUB)/lib -lmy_sub_pro1\



Sub projects access plugins by using standard QPluginLoader. I'm checking all files in my plugin build directory and cast them:


QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = loader.instance();
myPluginInterface* plugin = qobject_cast< myPluginInterface* > (plugin);

Any Main, Sub or plugin project that would like to use commons, is simply including them:


SOURCES += \

$$(COMMON)/common/calc.cpp




HEADERS += \

$$(COMMON)/common/calc.h

---

I've got problem with my application crashing without reason on closing: It crashes in malloc.c: malloc_consolidate (Full stack below). This makes it incredibly hard to debug. I used Valgrind till the moment it doesn't show any memory leaks, but the problem persists. My friend once told me, that he had some problems while using static variables in plugins. I think he was right, because when I got rid of them me application is now crashing less often. I also had a small problem after adding a constexpr, but after some time the problem disappeared and I couldn't reproduce it.

I cannot possibly paste all the code that might be causing problems. However I would like to sincerely ask for any idea that might cause problems on destruction in architecture that I'm using. I will be really thankful for any idea on what to check or what could be potential problems while creating program that is using a dynamic library that is using plugins. I couldn't find any similar topic on problems with Qt Plugins.

It is worth to mention that crash only occurs on closing, and all destructors are called properly. What is more, when I created a stand-alone program that simply uses one Subprogram with plugins it works perfectly. Additionally if I use MainProgram to call any Subprogram without plugins it also works effortlessly. I'm using Qt 5.3.2.

Stack view on crash:


0 malloc_consolidate malloc.c 5206
1 _int_free malloc.c 5079
2 QArrayData::deallocate 130
3 QTypedArrayData<int>::deallocate 234
4 QVector<int>::freeData 473
5 QVector<int>::~QVector 76
6 QRegExpEngine::~QRegExpEngine 1356
7 QCache<QRegExpEngineKey, QRegExpEngine>::clear 126
8 QCache<QRegExpEngineKey, QRegExpEngine>::~QCache 95
9 (anonymous namespace)::Q_QGS_globalEngineCache::Holder::~Hold er 3825
10 __cxa_finalize cxa_finalize.c 56
11 __do_global_dtors_aux /opt/Qt-5.3.2/lib/libQt5Core.so.5
12 ??
13 _dl_fini dl-fini.c 254

high_flyer
2nd August 2017, 17:19
Debugging an application without knowing the code (which is what you ask) is very difficult.
But lets start at your call stack:
Where do you use QVector<int>? (including in your plugins!)
It seems that while trying to destroy a vector the crash is occurring.
Depending on how often you use QVecot<int> (more precisely where QVectotr<int> gets destroyed, both via 'delete' or going out of scope) we can reduce the possible areas in the code where the crash is happening and start analyzing these code areas in more detail.

d_stranz
2nd August 2017, 17:42
I've got problem with my application crashing without reason on closing

I'll bet there is a reason sitting somewhere between the chair and the keyboard... :p

Crashing on program exit is often the result of double deletion - you delete something twice by mistake, or you delete something that Qt owns and is deleting for you. It can also happen if you call "delete" rather than "deleteLater()" on a QObject that is still in use by the Qt libraries.

gavinmagnus
2nd August 2017, 18:20
Thank you so much for your answer. I was sure that the stack I was getting was implying that problem occurs inside Qt library (that I'm not using it properly). After commenting all sections using QVector<int> I have successfully isolated the problem. It looks like the problem occurs when I was using common directory like this: Sub project was using the same common sources + headers as plugin:



//Sub_project.pro

SOURCES += \
$$(COMMON)/common/calc.cpp \

HEADERS +=\
$$(COMMON)/common/calc.h \

// my_plugin.pro (same as Sub_project.pro)

SOURCES += \
$$(COMMON)/common/calc.cpp \

HEADERS +=\
$$(COMMON)/common/calc.h \


It looks like I should have simply used INCLUDEPATH in my plugin project. As I understand the common library calc was compiled twice. I will need some time to test it.

Right now I'm getting a little more difficult problem: it crashes in QVector< QCustomTypeInfo >. I don't have any type declared with Q_DECLARE_METATYPE. Does this error mean any custom type I have created, like QVector < my_calc >? Is there any way I could presume which type is Qt talking about?

Thanks again for help, even without code. I just thought I cannot paste thousands lines of code and ask for a debugging. I'll try to paste the relevant code whenever possible.

d_stranz
2nd August 2017, 19:27
You are chasing a red herring here. There is no way I can see in which the build configuration of your project could have any effect on the runtime behavior except to cause errors in linking if you are somehow linking the same code more than once into a single binary (exe or dll). And if you get errors in linking, the exe or dll won't be built.

If you have common source code that is built into more than one binary, then you should isolate this code into its own static library and link that with each binary that needs it. But again, compiling and linking the same source code into different binaries should still not cause problems unless you are defining global variables or static member variables in classes in that code that end up being instantiated more than once.

If you are moving code around and are seeing crashes in different places, then I would say that something in your code is corrupting memory. It is a classic sign when a program crashes in a piece of code you aren't even aware you are using. The location of the crash is not the cause of the crash, it is just where the program tries to do something with the corrupted memory and goes off into limbo.

high_flyer
2nd August 2017, 21:47
After commenting all sections using QVector<int> I have successfully isolated the problem. It looks like the problem occurs when I was using common directory like this: Sub project was using the same common sources + headers as plugin:
like d_stranz, I don't see the connection between QVector<int> and your project configuration.
If the linker didn't complain about multiple definition of symbols that is NOT your problem.


Right now I'm getting a little more difficult problem: it crashes in QVector< QCustomTypeInfo >
This reinforces my original suspicion - that somewhere you you are deleting a vector not as you should.
My guess is, that you have pointer to such a vector (or possible multiple pointers) which get destroyed and leave a dangling pointer behind, which then again gets deleted - but that can't work of course.
This is of course pure speculation.
Again, without the code one can only guess.
Can you say in which object this crashes?
My guess this is a moc file.
Are you passing any vectors per signal slots?
Then its almost certainly the case.


I just thought I cannot paste thousands lines of code and ask for a debugging.
No need, just the places you either delete or have QVectors going out of scope.
Can't be THAT many.

Try building your application and plugins as a debug build, and run it from the debugger - this will save us all the guess work and show you exactly where the crashing line is.

And beyond that - the best thing you can do to fix this and make sure you fix many other problems you don't even know you have is write tests for your code - it will show you where you have problems and help you localize them.