17

Wikipedia says that "A piece of code is said to be exception-safe, if run-time failures within the code will not produce ill effects, such as memory leaks, garbled stored data, or invalid output. Exception-safe code must satisfy invariants placed on the code even if exceptions occur."

And it seems that we need exception handling for exception safety. Ot the other hand, exception handling is not very popular in Qt applications as long as I see.

What are your best practices in Qt to satisfy exception safety? What do you use instead of exception handling?

metdos
  • 13,411
  • 17
  • 77
  • 120
  • 1
    QT is a very old library and very poor when it comes to exception safety. Consider how all widgets have to be heap-allocated but there's no smart pointer for RAII. The best you can do is allocate them into an auto_ptr and release the memory to the parent/layout when inserting. They have some basic provisions like QMutexLocker since throwing while a mutex is locked would be disastrous, but there's a whole lot more they need to provide or a whole lot of work you'll have to do yourself to use qt in an exception-safe way. – stinky472 Jun 28 '10 at 13:59
  • 8
    @stinky472: Wrong. [QSharedPointer](http://doc.trolltech.com/4.6/qsharedpointer.html) – MSalters Jun 28 '10 at 14:25
  • @stinky472: Which GUI toolkits allow widgets to be stack-allocated? And why would you want to do this? Sounds like a "straw-man" argument. – kevinarpe Dec 30 '11 at 08:50
  • @KCArpe The statement was "Consider how all widgets have to be heap-allocated ***but there's no smart pointer for RAII." I'm not complaining about widgets being heap-allocated, that becomes quite essential through a design based on inheritance and polymorphism like QT. I'm complaining about lack of RAII and exception-safety in QT's memory management model. – stinky472 Jan 31 '12 at 19:42
  • 2
    Just consider this basic example from the official QT docs: menuBar = new QMenuBar; fileMenu = new QMenu(tr("&File"), this); What happens if operator new throws on creating fileMenu? Oops, memory leak. So again, QT is not designed for exception-safety. Even Nokia's examples are not correct from an exception-safety standpoint. – stinky472 Jan 31 '12 at 19:46
  • @MSalters not wrong, but we're talking in different contexts. QSharedPointer is not used, for example, by QLayout which assumes that the QWidget* pointer being passed to addWidget is one that QLayout deletes. If QSharedPointer was used across the board in QT, then it would be an exception-safe library, but currently most of Nokia's own examples are not exception-safe because there are many parts of the library that aren't using QSharedPointer or any kind of adherence to RAII. – stinky472 Feb 01 '12 at 15:21
  • So yes, QSharedPointer exists, but is not used for a lot of things involving, say, QWidget, so it really doesn't matter whether or not it exists in this context. Still a good portion of QT's library is based on clients passing in raw pointers to dynamically allocated objects. – stinky472 Feb 01 '12 at 15:23

4 Answers4

10

C++ has a very powerful mechanism for excpetion-safety. Destructors are run for all variables that go out of scope due to an exception. This differs from languages like Java, where exception-safety requires the programmer to get the catch and finally clauses right.

The C++ behavior of calling destructors works seamlessly with Qt objects on the stack. Qt classes all have destructors and none require manual cleanup. Furthermore, QSharedPointer<T> can be used to manage heap-allocated Qt objects; when the last pointer goes out of scope the object is destroyed. This includes the case where the pointer goes out of scope due to an exception.

So, exception-safety is certainly present in Qt. It's just transparent.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 2
    I think the problem with QSharedPointer is that it's not used in a lot of places. For example, a QLayout expects QWidget* with the expectation that QLayout becomes the memory manager for it. We can't use QSharedPointer here because QLayout is supposed to delete the widget when it is removed from the layout. :-( – stinky472 Jan 31 '12 at 19:50
  • 3
    The author's original post stated, "exception handling is not very popular in Qt applications as long as I see" which is precisely true. The existence of QSharedPointer changes nothing because few parts of the QT API and its examples actually use it. Instead we have examples like QButton* button = new QButton(...); QVBoxLayout* layout = new QVBoxLayout(...); The library is, for the most part, not coded to be exception-safe. It's something that should be addressed and making more parts of the library accept and store QSharedPointer would be a very good solution. – stinky472 Feb 01 '12 at 15:26
7

Qt is (mostly) not exception safe: http://doc.qt.io/archives/4.6/exceptionsafety.html

On the other hand dealing with exceptions correctly in event driven programming is very hard, so best is to avoid them when using Qt and pass error codes.

Christophe Weis
  • 2,518
  • 4
  • 28
  • 32
Artyom
  • 31,019
  • 21
  • 127
  • 215
2

My best practice is to not use (or at least avoid them as much as possible) C++ exceptions in Qt based code, which makes handling them a non-problem. Qt isn't really the reason for this though, I simply feel exceptions often make things unnecessarily more complicated than they should be. But it helps Qt itself is mostly exception troubles free... :)

Xenakios
  • 134
  • 1
  • 1
  • 2
1

Qt classes are exception neutral as stated in the documentation.

You should stick with boolean values for handling error conditions, just like Qt itself.

Not using exceptions internally was done for portability reasons, because Qt has to support many different platforms (portability and exceptions don't mix that well).

Again, from the docs:

Currently, the only supported use case for recovering from exceptions thrown within Qt (for example due to out of memory) is to exit the event loop and do some cleanup before exiting the application. Typical use case:

QApplication app(argc, argv);
 ...
 try {
     app.exec();
 } catch (const std::bad_alloc &) {
     // clean up here, e.g. save the session
     // and close all config files.

     return 0; // exit the application
 }
Bowdzone
  • 3,827
  • 11
  • 39
  • 52
the_void
  • 5,512
  • 2
  • 28
  • 34
  • 4
    Note that Qt has a history that goes back to the time when exceptions were new. Portability in the 21st century is a lot easier. – MSalters Jun 28 '10 at 08:30
  • You're right, I should have emphasized that. Although I don't really know much about exceptions and Symbian, especially with newer versions. I know older versions used a substantially different exception handling mechanism. – the_void Jun 28 '10 at 08:48
  • Symbian is a pain; no surprise given its 1980s EPOC roots. But Qt and Symbian aren't _that_ related. Symbian originated at Psion; Qt at TrollTech. – MSalters Jun 28 '10 at 14:34