Solved MacOs application crashes in QObject class when exit
-
Hi,
I'm having problem to exit the application correctly. When I exit the app the program crashes in a QObject class destructor. The class is a global class that uses QBluetoothSocket to communicate. I created it as a global class included in a global file because I need its method in almost every class of my application.
The constructor is the following:BluetoothClass::BluetoothClass() { socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); }
While the destructor is:
BluetoothClass::~BluetoothClass() { delete socket; }
The program in debug mode stops on the parenthesis after delete socket.
The file.h is like this:#ifndef BLUETOOTH_H #define BLUETOOTH_H #include <QBluetoothSocket> #include <QBluetoothUuid> #include <QDebug> #include <QTimer> class BluetoothClass : public QObject { Q_OBJECT public: BluetoothClass(); ~BluetoothClass(); //I also have some methods that I don't call to get this error, I just create the class }; #endif
The class is created in the global file.h like this:
extern BluetoothClass o_bluetooth;
and declared in the global file.cpp:
BluetoothClass o_bluetooth;
The disassembler shows me this output:
0x102b097a4 41 ff 46 0c incl 0xc(%r14)
I also know that this crash happens after the CloseEvent of the main QMainWindow.
I can't really understand what's the problem with this, does anyone have some suggestions? Or anything to try?I'm using:
-
Qt 5.12.2 clang 64 bit
-
MacOs 10.13.6
Thanks in advance!
-
-
@davidesalvetti said in MacOs application crashes in QObject class when exit:
extern BluetoothClass o_bluetooth;
Don't do that with Qt classes!
It can cause other issues as well. For example your app can terminate because a QObject based class is created before QApplication.
You should avoid such global objects.
Why don't you create it for example in main() and then pass pointer or reference to all other objects which need it?
Also, why do you allocate socket on the heap? Just do a normal member variable.int main() { QApplication app(...); BluetoothClass o_bluetooth; ... return app.exec() }
-
@jsulm Thanks for your answer! I do like that because I have a lot of classes in my project since my application is quite big, and I thought the easiest way to use a QObject in some of those classes was to create it as a global object. Moreover I should always pass the pointer from parent to child and so again, that would be a little messy. Isn't there another approach? Anyway if that's the right approach I will do like you said! Thanks again!
I will also remove the socket from the heap.Just another question: if I have created also some QThreads as global object should I behave like for Objects? But can I use such a global class for variable, structs and some Timer or it is inappropriate?
Thank you
-
Hi,
If you have the need for so many global objects in your project then you likely have a bigger architecture issue.
You really should take the time to go back to the drawing board. Global objects should be avoided. There are other design patterns that you can use when having to share stuff between different pieces of your application.
Take for example the model/view approach: you have one model and can set it on different views to make use or show the data in different ways.
-
@SGaist I don't understand what the model/view approach consist of. Can you point me to some links please?
-
The documentation is your friend.
For other design patterns, you can start by the Software Design Pattern article on Wikipedia.
-
@SGaist @jsulm Thanks for your answers! I was just wondering one thing. If I declare in the global file the BluetoothClass class as a pointer and then I create the class in the main.cpp so that the object is created after Application but I will continue to have the pointer to the class with its methods available in all the software, is it still inappropriate?
Something like this:
extern BluetoothClass *o_bluetooth int main() { QApplication app(...); o_bluetooth = new BluetoothClass(); ... return app.exec() }
-
If by inappropriate you mean a possible big source of trouble, hard do understand/reason about code, hard to find bug, maintenance hell in the making, then yes. If not, then please define inappropriate.
As already said several times, creating global objects because it's possible and maybe more easy to access is a really wrong idea. You are going to have race conditions because you are not protecting access to it properly. You are going to have issues knowing where it might be used and for what purpose. Also, how are you going to be able to properly write test for your code if you just pass around global objects ?
-
@SGaist by inappropriate I mean that it can cause a crash on closing the application, that is the problem this thread has been created for.
I understand that creating global objects it's not the right thing to do. I'm trying to understand if there is a workaround that does not consist of reviewing all the design pattern that would end up rewriting all the application from the begin. When I started I didn't know about all these problems, surely in the next project I will take care of them.
I do not have all my classes in a global file, don't get me wrong, I have all the classes created using the parent-child method. I just have this BluetoothClass Object and a few threads (3) that have been put in this global file. Now, I have the same application running on Windows without any problem (that's why I never worried about global QObjects), I've never had race conditions because threads are safely implemented using QMutex and they do completely different things (usually they never run all together), so I think is a Mac side problem.
The point is: is it possible that creating a global class like my BluetoothClass can cause the crash of the application on exit? Then @jsulm said that the problem is that creating a global class it's possible that the class is created before QApplication, so putting just the pointer on the global file and creating the class in the main after QApplication, will eventually remove the possibility of crashes like this?
-
@davidesalvetti said in MacOs application crashes in QObject class when exit:
so putting just the pointer on the global file and creating the class in the main after QApplication, will eventually remove the possibility of crashes like this?
You don't need to allocate your object on the heap in this case, just do:
int main() { QApplication app(...); BluetoothClass o_bluetooth; SomeOtherClass someOtherClass(&o_bluetooth); return app.exec() }
In this case o_bluetooth will be destroyed for you when main() finishes (so, no need for delete).
-
@jsulm Thank you! I will adopt your solution!