Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QMainWindow and std::shared_ptr (segfault at exit)
Forum Updated to NodeBB v4.3 + New Features

QMainWindow and std::shared_ptr (segfault at exit)

Scheduled Pinned Locked Moved Unsolved General and Desktop
16 Posts 4 Posters 5.9k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Pippin
    wrote on 2 Feb 2016, 10:38 last edited by Pippin 2 Feb 2016, 10:42
    #1

    Hello,

    I thought I was managing my pointers correctly but it seems that I'm deleting things twice. I have 7 public static member QMainWindows with no parents. I decided to create each of them in a std::shared_ptr so that they are deleted properly when the program exits (so not by Qt). The 7 windows are constructed with std::make_shared in the main function, after the construction of the QApplication instance (which is declared and constructed inside the main function, isn't a pointer and belongs to the stack).

    However I still get a segfault when the program ends, so how does it work? Why would my windows get destructed by Qt if they have no parents?

    Thanks in advance.

    In case I was too vague, here is some code:

    main.cpp

    int main(int argc, char *argv[])
    {
    	QApplication app(argc, argv);
    	app.setStyleSheet("QRadioButton { font: bold }");
    	app.setStyleSheet("QToolButton { background-color: transparent; border: none; }");
    	
    	WS::Window1 = std::make_shared<QMainWindowSubClass1>();
    	WS::Window2 = std::make_shared<QMainWindowSubClass2>();
    	WS::Window3 = std::make_shared<QMainWindowSubClass3>();
    	WS::Window4 = std::make_shared<QMainWindowSubClass4>();
    	WS::Window5 = std::make_shared<QMainWindowSubClass5>();
    	WS::Window6 = std::make_shared<QMainWindowSubClass6>();
    	WS::Window7 = std::make_shared<QMainWindowSubClass7>();
    	
    	WS::Window1->show();
    	return app.exec();
    }
    

    WS.hpp

    class WS
    {
    	public:
    	
    		static std::shared_ptr<QMainWindowSubClass1>			Window1;
    		static std::shared_ptr<QMainWindowSubClass2>			Window2;
    		static std::shared_ptr<QMainWindowSubClass3>			Window3;
    		static std::shared_ptr<QMainWindowSubClass4>			Window4;
    		static std::shared_ptr<QMainWindowSubClass5>			Window5;
    		static std::shared_ptr<QMainWindowSubClass6>			Window6;
    		static std::shared_ptr<QMainWindowSubClass7>			Window7;
    };
    
    1 Reply Last reply
    0
    • B Offline
      B Offline
      bsomervi
      wrote on 2 Feb 2016, 11:11 last edited by
      #2

      It looks like these objects are QWidget derivatives, do they get their parent set, directly or indirectly, anywhere. If so then they are probably having their lifetime managed by Qt as well.

      Quoted from the QWidget constructor documentation:

      "If parent is 0, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted."

      1 Reply Last reply
      0
      • P Offline
        P Offline
        Pippin
        wrote on 2 Feb 2016, 11:37 last edited by
        #3

        I'm afraid that each window has nullptr as its parent widget. I just checked that before posting.

        B 1 Reply Last reply 2 Feb 2016, 11:46
        0
        • P Pippin
          2 Feb 2016, 11:37

          I'm afraid that each window has nullptr as its parent widget. I just checked that before posting.

          B Offline
          B Offline
          bsomervi
          wrote on 2 Feb 2016, 11:46 last edited by
          #4

          @Pippin Ah, OK, you didn't say that.

          Are you sure the issues is due to double destruction? Is it possible that the real issue is due to your QApplication derivative being deleted before the QWidgets? Having the QWidgets at global scope is not the way QWidgets are supposed to be used, why do you need them at global scope? Why do you need std::shared_ptr, are they somehow shared between threads?

          Have you tried changing things so that the QWidget derivatives are created on the stack in the function that instantiates QApplication thus guaranteeing that their lifetime is within the lifetime of the QApplicationobject instance that runs them?

          1 Reply Last reply
          0
          • P Offline
            P Offline
            Pippin
            wrote on 2 Feb 2016, 11:50 last edited by
            #5

            @bsomervi

            First thanks for your replies!

            Well I need them to be "global variables", because they are used in several .cpp files. If I use ordinary pointers then I'll have to handle (delete) them myself, which is never a good idea. So I figured using shared pointers was the best/only option. If there are other ways I'm all ears!

            B 1 Reply Last reply 2 Feb 2016, 12:12
            0
            • P Pippin
              2 Feb 2016, 11:50

              @bsomervi

              First thanks for your replies!

              Well I need them to be "global variables", because they are used in several .cpp files. If I use ordinary pointers then I'll have to handle (delete) them myself, which is never a good idea. So I figured using shared pointers was the best/only option. If there are other ways I'm all ears!

              B Offline
              B Offline
              bsomervi
              wrote on 2 Feb 2016, 12:12 last edited by bsomervi 2 Feb 2016, 12:14
              #6

              @Pippin OK, so if you want a pointer to an object created on the stack then simply take its address or possibly pass a reference if, like in this case, the lifetime is guaranteed longer than the client. For example say you have a class client that needs to access one of your MainWindow object instances:

              class MyMainWindow
                 : public QMainWindow {
              // ...
              };
              
              class Client {
              public:
                 explicit Client (MyMainWindow * main_window)  // could be MyMainWindow& main_window
                    : main_window_ {main_window}
                 {}
              
                 // ...
              
              private:
                 MyMainWindow * main_window_;  // could be MyMainWindow& main_window
              };
                
              int main (int argc, char * argv[]) {
                 QApplication application {argc, argv};
                 MyMainWindow main_window;
                 Client client {&main_window};     // or Client client {main_window};  if references are used
                 application.exec ();
                 // guaranteed destruction order here is client then main_window then application
               }
              

              If you really want to create the QWidgets on the heap with no parent then use std::scoped_ptr to manage lifetime in the main() function. If the QWidget object instances might get destroyed while a client holds a pointer then use QPointer to hold the pointer as that can be used to check if the QObject derivative pointer it holds is still valid.

              Any of the above are better than global scope objects.

              1 Reply Last reply
              0
              • J Offline
                J Offline
                jsulm
                Lifetime Qt Champion
                wrote on 2 Feb 2016, 12:12 last edited by
                #7

                It is even a worse idea to have public static variables! If you have to use them across several cpp files why not just provide a get() method which returns a pointer (no need though to create them via new, just do "return &variable").

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 2 Feb 2016, 12:14 last edited by
                  #8

                  Hi,

                  To add to @jsulm, why exactly to you need them in several cpp files ? That smells light a huge tight coupling.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  B 1 Reply Last reply 2 Feb 2016, 12:16
                  0
                  • SGaistS SGaist
                    2 Feb 2016, 12:14

                    Hi,

                    To add to @jsulm, why exactly to you need them in several cpp files ? That smells light a huge tight coupling.

                    B Offline
                    B Offline
                    bsomervi
                    wrote on 2 Feb 2016, 12:16 last edited by
                    #9

                    @SGaist Indeed, I was going to ask why signals and slots were not an option for inter class communication rather than holding pointers or references.

                    1 Reply Last reply
                    0
                    • P Offline
                      P Offline
                      Pippin
                      wrote on 2 Feb 2016, 12:45 last edited by Pippin 2 Feb 2016, 12:46
                      #10

                      Thanks everyone for your replies, I'm still a bit confused as to what's best for my project. I wasn't aware of the existence of std::scoped_ptr, so I'll definitely use it if I can't use anything else.

                      These 7 windows have member functions that show or hide the other windows. For example, WS::Window1 can show WS::Window2 and WS::Window5 if that's what the user wants (they would both appear on top of WS::Window1). So WS::Window1 needs a pointer to WS::Window2 and another pointer to WS::Window5 in its .cpp file.

                      Same for the other windows, which all show other windows when the user requires it. The user spends his time browsing the 7 windows back and forth. This is why it's much simpler to make all 7 windows global. I'm not sure it's possible/easy to use references (and thus put these windows on the stack rather than on the heap) instead.

                      What would you guys do?

                      B 2 Replies Last reply 2 Feb 2016, 13:04
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 2 Feb 2016, 12:47 last edited by
                        #11

                        Then you should rather have a dedicated object that handles showing the right window at the right moment.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        1
                        • P Offline
                          P Offline
                          Pippin
                          wrote on 2 Feb 2016, 12:48 last edited by
                          #12

                          @SGaist Could you elaborate a bit please? How can I do that without causing any memory deletion issues?

                          1 Reply Last reply
                          0
                          • P Pippin
                            2 Feb 2016, 12:45

                            Thanks everyone for your replies, I'm still a bit confused as to what's best for my project. I wasn't aware of the existence of std::scoped_ptr, so I'll definitely use it if I can't use anything else.

                            These 7 windows have member functions that show or hide the other windows. For example, WS::Window1 can show WS::Window2 and WS::Window5 if that's what the user wants (they would both appear on top of WS::Window1). So WS::Window1 needs a pointer to WS::Window2 and another pointer to WS::Window5 in its .cpp file.

                            Same for the other windows, which all show other windows when the user requires it. The user spends his time browsing the 7 windows back and forth. This is why it's much simpler to make all 7 windows global. I'm not sure it's possible/easy to use references (and thus put these windows on the stack rather than on the heap) instead.

                            What would you guys do?

                            B Offline
                            B Offline
                            bsomervi
                            wrote on 2 Feb 2016, 13:04 last edited by bsomervi 2 Feb 2016, 13:05
                            #13

                            @Pippin std::shared_ptr<T> serves two specific purposes, (1) it can be used to extend the lifetime of the heap object instance of T for the owner of the shared_ptr and (2) it does that in a thread safe way so that heap object instances of T can be shared between threads. Note that using std::shared_ptr<T> does not implicitly make the T thread safe, it just makes the sharing mechanism thread safe i.e. the reference count.

                            There are other subtleties for sharing non-heap objects that involve a custom deletion function but none of the shared_ptr attributes are appropriate for your requirement.

                            Sorry I have mislead a little, there is no std::scoped_ptr<T>, I used boost::scoped_ptr<T> for so long that I forget it has another name in Standard C++ which is std::unique_ptr<T>. is a much simpler and lightweight class, it simply makes the lifetime of a heap object the same as its own with the exception that you can create the unique_ptr<T> before the T instance if you really want to, also you can explicitly release or change the managed object instance. The other big advantage of std::unique_ptr<T> is that it can be put into a Standard Library container.

                            1 Reply Last reply
                            0
                            • SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on 2 Feb 2016, 13:09 last edited by
                              #14

                              If you take QTabbedWidget, it's a set of widget that you can switch to by clicking on tab.

                              What allows your user to switch from one window to another ?

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              1 Reply Last reply
                              0
                              • P Offline
                                P Offline
                                Pippin
                                wrote on 2 Feb 2016, 13:10 last edited by
                                #15

                                @bsomervi Okay thanks again.

                                @SGaist Basically a QPushButton that shows another window.

                                1 Reply Last reply
                                0
                                • P Pippin
                                  2 Feb 2016, 12:45

                                  Thanks everyone for your replies, I'm still a bit confused as to what's best for my project. I wasn't aware of the existence of std::scoped_ptr, so I'll definitely use it if I can't use anything else.

                                  These 7 windows have member functions that show or hide the other windows. For example, WS::Window1 can show WS::Window2 and WS::Window5 if that's what the user wants (they would both appear on top of WS::Window1). So WS::Window1 needs a pointer to WS::Window2 and another pointer to WS::Window5 in its .cpp file.

                                  Same for the other windows, which all show other windows when the user requires it. The user spends his time browsing the 7 windows back and forth. This is why it's much simpler to make all 7 windows global. I'm not sure it's possible/easy to use references (and thus put these windows on the stack rather than on the heap) instead.

                                  What would you guys do?

                                  B Offline
                                  B Offline
                                  bsomervi
                                  wrote on 2 Feb 2016, 13:17 last edited by
                                  #16

                                  @Pippin said:

                                  Same for the other windows, which all show other windows when the user requires it. The user spends his time browsing the 7 windows back and forth. This is why it's much simpler to make all 7 windows global. I'm not sure it's possible/easy to use references (and thus put these windows on the stack rather than on the heap) instead.

                                  Look again at my example, it uses a pointer to a stack object. You are conflating pointer to objects and heap based objects which is wrong, pointers and the heap are different and basically unrelated concepts.

                                  Anyway, listen to what @SGaist is saying as decoupling the relationships between your abstractions (classes) is most important. A good rule of design is to have maximum coupling within an abstraction and minimum coupling between abstractions. That means having classes knowing about each other is usually a bad thing.

                                  1 Reply Last reply
                                  0

                                  1/16

                                  2 Feb 2016, 10:38

                                  • Login

                                  • Login or register to search.
                                  1 out of 16
                                  • First post
                                    1/16
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved