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. [SOLVED] Exception safety in widget constructors?
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] Exception safety in widget constructors?

Scheduled Pinned Locked Moved General and Desktop
22 Posts 6 Posters 12.5k Views 1 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.
  • G Offline
    G Offline
    goetz
    wrote on last edited by
    #8

    Sydius, that's right. The base class destructor can't clean up the mess the was made in the derived class' constructor. It has to be cleaned up there. I'm not sure if the base class destructor is even called in that case. IMHO, the best way is to wrap the critical code in a try block and to clean up in the catch block if something goes wrong. The pointers should be set to null before starting the try:

    @
    Notepad::Notepad()
    : textEdit(0),
    quitButton(0)
    {
    QVBoxLayout *layout = 0;

    try {
        textEdit = new QTextEdit(this);
    

    quitButton = new QPushButton(tr("Quit"), this);
      
         connect(quitButton, SIGNAL(clicked()), this, SLOT(quit()));
      
        layout = new QVBoxLayout;
         layout->addWidget(textEdit);
        layout->addWidget(quitButton);
      
         setLayout(layout);
    } catch(MyFancyException &e) {
    if(textEdit)
    delete textEdit;

        if(quitButton)
            delete quitButton;
    
        if(layout)
            delete layout;
    
        throw e;
    }
    

    setWindowTitle(tr("Notepad"));
    }
    @

    http://www.catb.org/~esr/faqs/smart-questions.html

    1 Reply Last reply
    0
    • I Offline
      I Offline
      ixSci
      wrote on last edited by
      #9

      There is no need in smart pointers or try blocks here. In Qt the QObject class is responsible for cleaning up during its destruction. Also QObject is a parent class of the majority of Qt classes include the GUI ones. Although your Notepad object has not been created yet its QObject parent was. Thus you'ill have no leaks if you properly set parent at the construction time.

      1 Reply Last reply
      0
      • S Offline
        S Offline
        Sydius
        wrote on last edited by
        #10

        [quote author="ixSci" date="1294168106"]There is no need in smart pointers or try blocks here. In Qt the QObject class is responsible for cleaning up during its destruction. Also QObject is a parent class of the majority of Qt classes include the GUI ones. Although your Notepad object has not been created yet its QObject parent was. Thus you'ill have no leaks if you properly set parent at the construction time. [/quote]

        Ahh, actually you're correct. I was mistaken in believing that the base class destructor would not be called. Thank you for this clarification, it seems that Gerolf's original solution will be sufficient!

        1 Reply Last reply
        0
        • P Offline
          P Offline
          Panke
          wrote on last edited by
          #11

          It is sufficient except that the layout (and the widgets added to it) will leak before the call to setLayout()

          1 Reply Last reply
          0
          • I Offline
            I Offline
            ixSci
            wrote on last edited by
            #12

            Qt claims its classes are exceptions free(bold statement but almost true) that is why there is no leaks at the code presented above.

            1 Reply Last reply
            0
            • G Offline
              G Offline
              goetz
              wrote on last edited by
              #13

              The layout does not have a parent and is therefore not caught by the QObject destructor, that's right. The layout is in the parent-child hierarchy only after setLayout() in line 17.

              http://www.catb.org/~esr/faqs/smart-questions.html

              1 Reply Last reply
              0
              • I Offline
                I Offline
                ixSci
                wrote on last edited by
                #14

                Volker, exactly. But there are no possible exceptions between layout creation and its adoption by the QObject.
                This ctor seems truly exception neutral to me.

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  goetz
                  wrote on last edited by
                  #15

                  In this very case, yes. But if someone does some other object creation or manipulation inbetween that can throw an exception, it can raise a problem.

                  http://www.catb.org/~esr/faqs/smart-questions.html

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    Sydius
                    wrote on last edited by
                    #16

                    [quote author="Volker" date="1294174797"]In this very case, yes. But if someone does some other object creation or manipulation inbetween that can throw an exception, it can raise a problem.[/quote]

                    Having just "looked it up":http://doc.trolltech.com/latest/qvboxlayout.html, it appears that QVBoxLayout can take a parent, which should alleviate this concern?

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      BlackDante
                      wrote on last edited by
                      #17

                      [quote author="Volker" date="1294166366"]
                      @
                      Notepad::Notepad()
                      : textEdit(0),
                      quitButton(0)
                      {
                      QVBoxLayout *layout = 0;

                      try {
                          textEdit = new QTextEdit(this);
                      

                      quitButton = new QPushButton(tr("Quit"), this);
                        
                           connect(quitButton, SIGNAL(clicked()), this, SLOT(quit()));
                        
                          layout = new QVBoxLayout;
                           layout->addWidget(textEdit);
                          layout->addWidget(quitButton);
                        
                           setLayout(layout);
                      } catch(MyFancyException &e) {
                      if(textEdit)
                      delete textEdit;

                          if(quitButton)
                              delete quitButton;
                      
                          if(layout)
                              delete layout;
                      
                          throw e;
                      }
                      

                      setWindowTitle(tr("Notepad"));
                      }
                      @[/quote]

                      Hi, I have a question no related with topic but about this code. Why function "throw" is in a catch block? It is possible to do that? In this example I am little confused because I always been learnig that try block must throw the exception and in catch we catching this exception, in my university it is somethink like hard rule.

                      sorry for my broken english :)

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        Sydius
                        wrote on last edited by
                        #18

                        [quote author="BlackDante" date="1294179880"]
                        Hi, I have a question no related with topic but about this code. Why function "throw" is in a catch block? It is possible to do that? In this example I am little confused because I always been learnig that try block must throw the exception and in catch we catching this exception, in my university it is somethink like hard rule. [/quote]

                        It is common practice to "rethrow" an exception from a catch block after handling it if it is not the top-level catch. This allows it to propagate to the top-most catch block, if appropriate. Having more than a top-level try/catch block is to be avoided as it's typically unnecessary (as is true in this case), and it makes little sense to rethrow from the top-most catch, which might be where you got this impression. When they do have to be nested, though, it's usually appropriate to rethrow it.

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          BlackDante
                          wrote on last edited by
                          #19

                          oh, now I understand :) thanks for explain :)

                          sorry for my broken english :)

                          1 Reply Last reply
                          0
                          • I Offline
                            I Offline
                            ixSci
                            wrote on last edited by
                            #20

                            Also you don't have to specify an object when you need to rethrow exception inside a catch block. You just need to type throw; and it will rethrow source object. Moreover you can use some languages tricks such as automated rethrow when using try\catch function block in a ctor.
                            Example:
                            @Notepad()
                            try
                            {
                            //blalala
                            throw "Exception";
                            }catch(...)
                            {
                            //it will rethrow automatically
                            }@

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              goetz
                              wrote on last edited by
                              #21

                              I will definitely have to dive deeper into that exception thingy in the future. So fare I only use that in my Java code and to catch errors from GraphicsMagick. Thanks for that tip, ixSci!

                              http://www.catb.org/~esr/faqs/smart-questions.html

                              1 Reply Last reply
                              0
                              • P Offline
                                P Offline
                                Panke
                                wrote on last edited by
                                #22

                                try-function-blocks are the only way to catch exceptions from the initializer list, too. I would leave a comment every time you use it. Its very simple to forget the auto-rethrow thing. My recommended reading for exception handling is "german article ":http://tinyurl.com/3yuh57x and Bjarne himself "Exception safety in TC++PL":http://www.research.att.com/~bs/3rd_safe0.html

                                1 Reply Last reply
                                0

                                • Login

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