<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to Exceptions_and_OWLNext</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>Recent changes to Exceptions_and_OWLNext</description><atom:link href="https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/feed" rel="self"/><language>en</language><lastBuildDate>Sun, 06 Apr 2025 18:34:37 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/feed" rel="self" type="application/rss+xml"/><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v31
+++ v32
@@ -225,7 +225,7 @@
   c.CloseClipboard();
 ~~~

-Now, if there is an exception in this code, the &lt;tt&gt;unique_ptr&lt;/tt&gt; destructor will call the specified deleter to clean up the allocated resource it refers to. And all is well, even if a reckless programmer should later add that SaveToLog call.
+Now, if there is an exception in this code, the &lt;tt&gt;unique_ptr&lt;/tt&gt; destructor will call the specified deleter to clean up the allocated resource it refers to. And all is well, even if you later add that SaveToLog call.

 &lt;br/&gt;

&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Sun, 06 Apr 2025 18:34:37 -0000</pubDate><guid>https://sourceforge.net1028876a46377ef6664d407efb1849022dff9868</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v30
+++ v31
@@ -168,7 +168,7 @@
 &lt;hr/&gt;
 ## Expect an exception — write exception-safe code

-Unlike Windows API C code, OWLNext is C++ code, and you should expect that any function and constructor may throw an exception, unless it is explicitly stated in the API that it does not (i.e. the function signature has &lt;tt&gt;noexcept&lt;/tt&gt; applied, or the now deprecated &lt;tt&gt;throw()&lt;/tt&gt; specification). Unfortunately, as OWLNext is a thin wrapper for the Windows API, many programmers copy-and-paste code from the Windows documentation into their programs, code that is not written for exception safety. In particular, this becomes a big problem with functions that allocate resources, such as memory, GDI objects and file handles. Since an exception may occur, resources may leak, unless you carefully write your program to clean up, either by explicit exception handlers, or much more smartly, by using C++ code constructs, such as smart pointers, that exploit [RAII](http://en.cppreference.com/w/cpp/language/raii) to deallocate resources automatically.
+Unlike Windows API C code, OWLNext is C++ code, and you should expect that any function and constructor may throw an exception, unless it is explicitly stated in the API that it does not (i.e. the function signature has &lt;tt&gt;noexcept&lt;/tt&gt; applied, or the now deprecated &lt;tt&gt;throw()&lt;/tt&gt; specification). Unfortunately, as OWLNext is a thin wrapper for the Windows API, many programmers copy-and-paste code from the Windows documentation into their programs — code that is not written for exception safety. In particular, this becomes a big problem with functions that allocate resources, such as memory, GDI objects and file handles. Since an exception may occur, resources may leak, unless you carefully write your program to clean up, either by explicit exception handlers, or better yet, by using C++ code constructs, such as smart pointers, that exploit [RAII](http://en.cppreference.com/w/cpp/language/raii) to deallocate resources automatically.

 As an example, let us consider copying the contents of a List Box onto the clipboard. If you rely on the Windows API [clipboard example code](https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016.aspx#_win32_Copying_Information_to_the_Clipboard), you may end up with something looking as follows:

&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Sun, 06 Apr 2025 18:30:32 -0000</pubDate><guid>https://sourceforge.net89db5f717caae35dad3bfbb12b2fa99dd6ef3683</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v29
+++ v30
@@ -107,14 +107,12 @@
 ~~~C++
   catch (const std::runtime_exception&amp;amp;)
   {
-    const auto cancelQuit = [&amp;amp;]
-      {
-      for (auto m = MSG{}; ::PeekMessage(&amp;amp;m, nullptr, 0, 0, PM_REMOVE); ProcessMsg(m))
-        if (m.message == WM_QUIT)
-          return true;
-      return false;
-      };
-    const auto didCancelQuit = cancelQuit();
+    const auto cancelQuit = []
+    {
+      auto m = MSG{};
+      return ::PeekMessage(&amp;amp;m, nullptr, WM_QUIT, WM_QUIT, PM_REMOVE) == TRUE;
+    };
+    [[maybe_unused]] const auto didCancelQuit = cancelQuit();
     WARN(didCancelQuit, "Cancelled WM_QUIT message caused by unhandled exception.");    
     GetMainWindow()-&amp;gt;EnableWindow(true);
     GetMainWindow()-&amp;gt;MessageBox("Something went wrong. Let's ignore it and hope for the best.");
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Sun, 18 Dec 2022 07:37:41 -0000</pubDate><guid>https://sourceforge.net168806465cf04b41481c8a740af0132512890905</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v28
+++ v29
@@ -1,7 +1,7 @@
 # Exceptions and OWLNext
 Although OWL uses C++ exceptions, OWL and early parts of OWLNext were written in an era when C++ exception handling was poorly understood. Consequently, much of the code is written without concern for exceptions, leaving the potential for memory leaks and undefined behaviour.

-Since then the concept of exception safety has been established, and we now have firm coding guidelines for writing exception-safe code (see [Exception Safety](http://en.wikipedia.org/wiki/Exception_safety) at Wikipedia). Improving the OWLNext code in this regard is an ongoing effort. In client code, you should assume that any OWLNext function may throw exceptions, unless it is declared `noexcept` or `throw()`.
+Since then the concept of exception safety has been established, and we now have firm coding guidelines for writing exception-safe code (see [Exception Safety](http://en.wikipedia.org/wiki/Exception_safety) at Wikipedia). Improving the OWLNext code in this regard is an ongoing effort. In client code, you should assume that any OWLNext function may throw exceptions, unless it is declared &lt;tt&gt;noexcept&lt;/tt&gt; or &lt;tt&gt;throw()&lt;/tt&gt;.

 This article looks closer at some areas of OWLNext where exception handling is of particular importance and provides some guidelines on how to write exception-safe OWLNext applications.

@@ -12,9 +12,9 @@
 &lt;hr/&gt;
 ## OWLNext now uses the std::exception base class

-Originally, OWL used the old exception class `xmsg` as the base class for [TXBase](http://owlnext.sourceforge.net/help/html/dd/d4d/classowl_1_1_t_x_base.html), which in turn is the base class for [TXOwl](http://owlnext.sourceforge.net/help/html/dc/d35/classowl_1_1_t_x_owl.html) and the derived exception classes, [TXWindow](http://owlnext.sourceforge.net/help/html/d0/d99/classowl_1_1_t_x_window.html) etc. OWLNext now uses [std::exception](http://en.cppreference.com/w/cpp/error/exception) as the base class for TXBase.
-
-The diagnostics macros, [CHECK](http://owlnext.sourceforge.net/help/html/d5/d16/checks_8h.html#a3e1cfef60e774a81f30eaddf26a3a274) and [PRECONDITION](http://owlnext.sourceforge.net/help/html/d5/d16/checks_8h.html#a919839494157b26458b38f1e3e1b3b1d), originally threw exceptions `check` and `precondition` derived from `xerror`, which in turn was derived from `xmsg`. OWLNext replaces these exception classes by [TCheckFailure](http://owlnext.sourceforge.net/help/html/d5/d2e/classowl_1_1_t_check_failure.html) and [TPreconditionFailure](http://owlnext.sourceforge.net/help/html/d5/d12/classowl_1_1_t_precondition_failure.html) derived from [TDiagException](http://owlnext.sourceforge.net/help/html/d3/d68/classowl_1_1_t_diag_exception.html), which in turn is derived from std::exception.
+Originally, OWL used the old exception class &lt;tt&gt;xmsg&lt;/tt&gt; as the base class for [TXBase](http://owlnext.sourceforge.net/help/html/dd/d4d/classowl_1_1_t_x_base.html), which in turn is the base class for [TXOwl](http://owlnext.sourceforge.net/help/html/dc/d35/classowl_1_1_t_x_owl.html) and the derived exception classes, [TXWindow](http://owlnext.sourceforge.net/help/html/d0/d99/classowl_1_1_t_x_window.html) etc. OWLNext now uses [std::exception](http://en.cppreference.com/w/cpp/error/exception) as the base class for TXBase.
+
+The diagnostics macros, [CHECK](http://owlnext.sourceforge.net/help/html/d5/d16/checks_8h.html#a3e1cfef60e774a81f30eaddf26a3a274) and [PRECONDITION](http://owlnext.sourceforge.net/help/html/d5/d16/checks_8h.html#a919839494157b26458b38f1e3e1b3b1d), originally threw exceptions &lt;tt&gt;check&lt;/tt&gt; and &lt;tt&gt;precondition&lt;/tt&gt; derived from &lt;tt&gt;xerror&lt;/tt&gt;, which in turn was derived from &lt;tt&gt;xmsg&lt;/tt&gt;. OWLNext replaces these exception classes by [TCheckFailure](http://owlnext.sourceforge.net/help/html/d5/d2e/classowl_1_1_t_check_failure.html) and [TPreconditionFailure](http://owlnext.sourceforge.net/help/html/d5/d12/classowl_1_1_t_precondition_failure.html) derived from [TDiagException](http://owlnext.sourceforge.net/help/html/d3/d68/classowl_1_1_t_diag_exception.html), which in turn is derived from std::exception.
 &lt;br/&gt;

 &lt;hr/&gt;
@@ -43,8 +43,7 @@

 For example, consider this simplified example from an actual OWLNext application that ran into this issue:

-~~~
-:::C++
+~~~C++
 void TMyApp::CmSelectWindowLayout()
 {
   try
@@ -65,8 +64,7 @@

 The recommended way to deal with this issue is simply not to attempt to handle exceptions eminating from dialog box execution, or any other OWLNext call that invokes message loops and callbacks (event handlers). Just let those exceptions through, so that they are reported and the application exits gracefully. Only handle exceptions in your own code, or in OWLNext code you can prepare for. For example:

-~~~
-:::C++
+~~~C++
 void TMyApp::CmSelectWindowLayout()
 {
   TWindowLayout layout;
@@ -85,8 +83,7 @@

 However, if you really need to handle any exception in cases like this, you need to remove WM_QUIT from the message queue. A brute-force way to do that is to call TMsgThread::FlushQueue. In our example, we also need to ensure that the main window is re-enabled, since a failure in the modal dialog box may have left it disabled.

-~~~
-:::C++
+~~~C++
 void TMyApp::CmSelectWindowLayout()
 {
   try
@@ -107,8 +104,7 @@

 Note that calling FlushQueue may cause your application to miss important messages. A more robust solution is to manually remove only WM_QUIT:

-~~~
-:::C++
+~~~C++
   catch (const std::runtime_exception&amp;amp;)
   {
     const auto cancelQuit = [&amp;amp;]
@@ -135,7 +131,7 @@

 For example, see the implementation of [TDocManager::CreateDoc](http://owlnext.sourceforge.net/help/html/d6/d91/classowl_1_1_t_doc_manager.html#ab82b1ae44b687ab92e2a94e31c5d103d). It calls [InitDoc](http://owlnext.sourceforge.net/help/html/d6/d91/classowl_1_1_t_doc_manager.html#a82bb14198f45278c9fb2f2c206a8793a), which in turn calls virtual functions [TDocument::SetDocPath](http://owlnext.sourceforge.net/help/html/d1/d00/classowl_1_1_t_document.html#ac7837d1cca22a4ca35df778abd2659e2), [InitDoc](http://owlnext.sourceforge.net/help/html/d1/d00/classowl_1_1_t_document.html#a64558fc26508b0fc43bf39f4c2ebb700) and [Open](http://owlnext.sourceforge.net/help/html/d1/d00/classowl_1_1_t_document.html#ab0ab51143a66314d05463936c543f449) without any exception handling. InitDoc also calls [CreateView](http://owlnext.sourceforge.net/help/html/d6/d91/classowl_1_1_t_doc_manager.html#ac86e84998ba732f7a807a9479cdab8f7), which in turn calls virtual function [TDocTemplate::ConstructView](http://owlnext.sourceforge.net/help/html/d7/d2f/classowl_1_1_t_doc_template.html#ac91c6d593ca0405ba5b1fc5597fbac53). If any of these functions throws an exception, then CreateDoc will leak the TDocument it failed to create [bugs:#344].

-Hence, the advice is to never let an exception escape an overriding virtual function, unless you are confident it will be handled properly by OWLNext. Many of the virtual functions are designed to return an error code on failure (such as `nullptr` or `false`). So if possible, translate all exceptions, except diagnostics exceptions, to the appropriate error code in your overriding function. If you do let exceptions escape, inspect the OWLNext source code to make sure it handles it in a satisfactory manner, and test well (with actual exceptions!).
+Hence, the advice is to never let an exception escape an overriding virtual function, unless you are confident it will be handled properly by OWLNext. Many of the virtual functions are designed to return an error code on failure (such as &lt;tt&gt;nullptr&lt;/tt&gt; or &lt;tt&gt;false&lt;/tt&gt;). So if possible, translate all exceptions, except diagnostics exceptions, to the appropriate error code in your overriding function. If you do let exceptions escape, inspect the OWLNext source code to make sure it handles it in a satisfactory manner, and test well (with actual exceptions!).
 &lt;br/&gt;

 &lt;hr/&gt;
@@ -153,8 +149,7 @@

 Normally, you don't have to do anything. Diagnostics exceptions will just automatically pass through your code. However, sometimes you may need to catch std::exception, on which [TDiagException](http://owlnext.sourceforge.net/help/html/d3/d68/classowl_1_1_t_diag_exception.html) is based, or you may need to catch everything. In such case, to let diagnostics exceptions pass through your exception handling code, you can filter them out by catching TDiagException and simply rethrowing it. Put the catch block for TDiagException before any other block. For example:

-~~~~
-:::C++
+~~~C++
 try
 {
   //...some code...
@@ -167,7 +162,7 @@
 {
   //...handle any other exceptions...
 }
-~~~~
+~~~

 If your catch block is located inside a Windows API callback, from which you cannot let any exception escape, you can call [TApplication::SuspendThrow](http://owlnext.sourceforge.net/help/html/dd/dfb/classowl_1_1_t_application.html#a7f106330fe650a91ed8656e5a7873994) rather than rethrowing the TDiagException. If your code instigated the callback, then insert a call to [TApplication::ResumeThrow](http://owlnext.sourceforge.net/help/html/dd/dfb/classowl_1_1_t_application.html#a350888023df6969a3bf5eaf51cd148b3) after the instigating call. If using SuspendThrow and ResumeThrow is not feasible, then report or log the error and immediately shut down the application.
 &lt;br/&gt;
@@ -175,12 +170,11 @@
 &lt;hr/&gt;
 ## Expect an exception — write exception-safe code

-Unlike Windows API C code, OWLNext is C++ code, and you should expect that any function and constructor may throw an exception, unless it is explicitly stated in the API that it does not (i.e. the function signature has `noexcept` applied, or the now deprecated `throw()` specification). Unfortunately, as OWLNext is a thin wrapper for the Windows API, many programmers copy-and-paste code from the Windows documentation into their programs, code that is not written for exception safety. In particular, this becomes a big problem with functions that allocate resources, such as memory, GDI objects and file handles. Since an exception may occur, resources may leak, unless you carefully write your program to clean up, either by explicit exception handlers, or much more smartly, by using C++ code constructs, such as smart pointers, that exploit [RAII](http://en.cppreference.com/w/cpp/language/raii) to deallocate resources automatically.
+Unlike Windows API C code, OWLNext is C++ code, and you should expect that any function and constructor may throw an exception, unless it is explicitly stated in the API that it does not (i.e. the function signature has &lt;tt&gt;noexcept&lt;/tt&gt; applied, or the now deprecated &lt;tt&gt;throw()&lt;/tt&gt; specification). Unfortunately, as OWLNext is a thin wrapper for the Windows API, many programmers copy-and-paste code from the Windows documentation into their programs, code that is not written for exception safety. In particular, this becomes a big problem with functions that allocate resources, such as memory, GDI objects and file handles. Since an exception may occur, resources may leak, unless you carefully write your program to clean up, either by explicit exception handlers, or much more smartly, by using C++ code constructs, such as smart pointers, that exploit [RAII](http://en.cppreference.com/w/cpp/language/raii) to deallocate resources automatically.

 As an example, let us consider copying the contents of a List Box onto the clipboard. If you rely on the Windows API [clipboard example code](https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016.aspx#_win32_Copying_Information_to_the_Clipboard), you may end up with something looking as follows:

-~~~
-:::C++
+~~~C++
   auto os = tostringstream{};
   const auto n = ListBox.GetCount();
   for (auto i = 0; i != n; ++i)
@@ -202,10 +196,9 @@
   c.CloseClipboard();
 ~~~

-Unfortunately, this  code will leak the global memory allocated by GlobalAlloc, if any following function call throws an exception before the SetCliboardData call takes ownership of the handle. It is also brittle with regard to the lock it acquires by calling GlobalLock. Although there is no intervening code that can throw exceptions between the acquisition and return of the lock (`memcpy_s` does not throw exceptions), this may change over time as the code is maintained. For example, a reckless programmer (probably yourself) may later add a C++ function call, say `SaveToLog`, that may throw exceptions.
-
-~~~
-:::C++
+Unfortunately, this  code will leak the global memory allocated by GlobalAlloc, if any following function call throws an exception before the SetCliboardData call takes ownership of the handle. It is also brittle with regard to the lock it acquires by calling GlobalLock. Although there is no intervening code that can throw exceptions between the acquisition and return of the lock (&lt;tt&gt;memcpy\_s&lt;/tt&gt; does not throw exceptions), this may change over time as the code is maintained. For example, a reckless programmer (probably yourself) may later add a C++ function call, say SaveToLog, that may throw exceptions.
+
+~~~C++
   const auto buf = GlobalLock(h); CHECK(buf);
   memcpy_s(buf, bufSize, s.c_str(), bufSize);
   SaveToLog(_T("Copied to clipboard: "), static_cast&amp;lt;lpctstr&amp;gt;(buf)); // *** BIG PROBLEM! MAY THROW! ***
@@ -214,8 +207,7 @@

 Fortunately, modern C++ has tools to help us write exception-safe code with little effort. In particular, the smart pointer [std::unique_ptr](http://en.cppreference.com/w/cpp/memory/unique_ptr) is immensly helpful, since it can be configured to take a custom *deleter*.  By exploiting this, we can rewrite the code to be exception-safe.

-~~~
-:::C++
+~~~C++
   const auto bufSize = (s.size() + 1) * sizeof(tchar);
   using THandle = std::unique_ptr&amp;lt;void, decltype(&amp;amp;globalfree)=""&amp;gt;;
   auto h = THandle{GlobalAlloc(GMEM_MOVEABLE, bufSize), &amp;amp;GlobalFree};
@@ -235,7 +227,7 @@
   c.CloseClipboard();
 ~~~

-Now, if there is an exception in this code, the `unique_ptr` destructor will call the specified deleter to clean up the allocated resource it refers to. And all is well, even if a reckless programmer should later add that `SaveToLog` call.
+Now, if there is an exception in this code, the &lt;tt&gt;unique_ptr&lt;/tt&gt; destructor will call the specified deleter to clean up the allocated resource it refers to. And all is well, even if a reckless programmer should later add that SaveToLog call.

 &lt;br/&gt;

&amp;lt;/void,&amp;gt;&amp;lt;/lpctstr&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Sat, 17 Dec 2022 00:38:30 -0000</pubDate><guid>https://sourceforge.net04faf1240c1ef65c14f04c024e1c6e681a02ba4b</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v27
+++ v28
@@ -139,6 +139,14 @@
 &lt;br/&gt;

 &lt;hr/&gt;
+## Exceptions in constructors
+
+As for virtual functions, the advice is to never let an exception escape the constructor of a class derived from OWL, unless you are confident it will be handled properly by OWLNext.
+
+For example, an exception in a constructor of a class derived from TView may lead to a dangling or double-deleted TDocument depending on the particular situation, the setting of the flag &lt;tt&gt;dtAutoDelete&lt;/tt&gt;, and the version of OWLNext. See [bugs:#543].
+&lt;br/&gt;
+
+&lt;hr/&gt;
 ## Do not swallow diagnostics exceptions

 In general, you should be careful not to swallow diagnostics exceptions in your code. The whole point of the diagnostics exceptions, e.g. generated by [CHECK](http://owlnext.sourceforge.net/help/html/d5/d16/checks_8h.html#a3e1cfef60e774a81f30eaddf26a3a274) and [PRECONDITION](http://owlnext.sourceforge.net/help/html/d5/d16/checks_8h.html#a919839494157b26458b38f1e3e1b3b1d), is to alert you to a problem in the code.
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Sat, 17 Dec 2022 00:19:12 -0000</pubDate><guid>https://sourceforge.netefd491118bb350b084792e42ea4e54b425317c79</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v26
+++ v27
@@ -39,7 +39,7 @@

 ### Dealing with rethrown exceptions and WM_QUIT

-If you do try to handle exceptions in your event handlers, you need to pay attention to exceptions rethrown by the exception transport machinery.  To ensure that unhandled exceptions reach the main message loop, OWLNext calls PostQuitMessage when an unhandled exception is caught and suspended (this change was introduced with the reintroduction of exception transport in version 6.34, see [bugs:#230](https://sourceforge.net/p/owlnext/bugs/230/#2971)). The call to PostQuitMessage ensures that all message loops are terminated, that the exception is rethrown and that it is ultimately handled and reported by the OWLNext startup code. However, this may lead to surprises and program bugs if you try to handle a rethrown exception in your code. In particular, since WM_EXIT is pending in this case, any call to MessageBox will not display, and the application will terminate, despite your exception handling, unless you remove WM_EXIT from the message queue.
+If you do try to handle exceptions in your event handlers, you need to pay attention to exceptions rethrown by the exception transport machinery.  To ensure that unhandled exceptions reach the main message loop, OWLNext calls PostQuitMessage when an unhandled exception is caught and suspended (this change was introduced with the reintroduction of exception transport in version 6.34, see [bugs:#230](https://sourceforge.net/p/owlnext/bugs/230/#2971)). The call to PostQuitMessage ensures that all message loops are terminated, that the exception is rethrown and that it is ultimately handled and reported by the OWLNext startup code. However, this may lead to surprises and program bugs if you try to handle a rethrown exception in your code. In particular, since WM_QUIT is pending in this case, any call to MessageBox will not display, and the application will terminate, despite your exception handling, unless you remove WM_QUIT from the message queue.

 For example, consider this simplified example from an actual OWLNext application that ran into this issue:

@@ -119,7 +119,7 @@
       return false;
       };
     const auto didCancelQuit = cancelQuit();
-    WARN(didCancelQuit, "Cancelled WM_QUIT message caused by unhandled exception");    
+    WARN(didCancelQuit, "Cancelled WM_QUIT message caused by unhandled exception.");    
     GetMainWindow()-&amp;gt;EnableWindow(true);
     GetMainWindow()-&amp;gt;MessageBox("Something went wrong. Let's ignore it and hope for the best.");
   }
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Tue, 14 Jan 2020 18:15:00 -0000</pubDate><guid>https://sourceforge.net3e4aa3f2224739fd8220ccd37daf713dac573073</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v25
+++ v26
@@ -35,6 +35,97 @@
 ## Exceptions in event handlers

 As described above, exception transport is provided for event handlers defined in OWLNext response tables, as well as virtual functions on the call chain between ReceiveMessage and the handler (see [TWindow::WindowProc](http://owlnext.sourceforge.net/help/html/d0/d5f/classowl_1_1_t_window.html#a6c575ef4a5d0f9a76b820490c41fcdb5)). However, you must still handle exceptions in your event handlers, unless it is OK for the application to shut down when an exception occurs (such as for diagnostics exceptions).
+&lt;br/&gt;
+
+### Dealing with rethrown exceptions and WM_QUIT
+
+If you do try to handle exceptions in your event handlers, you need to pay attention to exceptions rethrown by the exception transport machinery.  To ensure that unhandled exceptions reach the main message loop, OWLNext calls PostQuitMessage when an unhandled exception is caught and suspended (this change was introduced with the reintroduction of exception transport in version 6.34, see [bugs:#230](https://sourceforge.net/p/owlnext/bugs/230/#2971)). The call to PostQuitMessage ensures that all message loops are terminated, that the exception is rethrown and that it is ultimately handled and reported by the OWLNext startup code. However, this may lead to surprises and program bugs if you try to handle a rethrown exception in your code. In particular, since WM_EXIT is pending in this case, any call to MessageBox will not display, and the application will terminate, despite your exception handling, unless you remove WM_EXIT from the message queue.
+
+For example, consider this simplified example from an actual OWLNext application that ran into this issue:
+
+~~~
+:::C++
+void TMyApp::CmSelectWindowLayout()
+{
+  try
+  {
+    TWindowLayout layout;
+    TWindowLayoutSelectionDlg dlg(GetMainWindow(), layout);
+    if (dlg.Execute() == IDOK)
+      RestoreWindowLayout(layout);
+  }
+  catch (const std::runtime_exception&amp;amp;)
+  {
+    GetMainWindow()-&amp;gt;MessageBox("Something went wrong. Let's ignore it and hope for the best.");
+  }
+}
+~~~
+
+Now, if there is an unhandled exception in any of the event handlers in TWindowLayoutSelectionDlg, it will be suspended and PostQuitMessage will be called. This breaks the dialog message loop, and the exception is rethrown (by a call to ResumeThrow in in TDialog::Execute). However, since PostQuitMessage has been called, WM_QUIT is now pending in the message queue, so the MessageBox in our catch block does not show up. Our function ends, WM_QUIT is handled by the main message loop, and the application shuts down without any warning. Oops.
+
+The recommended way to deal with this issue is simply not to attempt to handle exceptions eminating from dialog box execution, or any other OWLNext call that invokes message loops and callbacks (event handlers). Just let those exceptions through, so that they are reported and the application exits gracefully. Only handle exceptions in your own code, or in OWLNext code you can prepare for. For example:
+
+~~~
+:::C++
+void TMyApp::CmSelectWindowLayout()
+{
+  TWindowLayout layout;
+  TWindowLayoutSelectionDlg dlg(GetMainWindow(), layout);
+  if (dlg.Execute() == IDOK)
+    try
+    {
+      RestoreWindowLayout(layout);
+    }
+    catch (const std::runtime_exception&amp;amp;)
+    {
+      GetMainWindow()-&amp;gt;MessageBox("Unable to restore this window layout. Try another.");
+    }
+}
+~~~
+
+However, if you really need to handle any exception in cases like this, you need to remove WM_QUIT from the message queue. A brute-force way to do that is to call TMsgThread::FlushQueue. In our example, we also need to ensure that the main window is re-enabled, since a failure in the modal dialog box may have left it disabled.
+
+~~~
+:::C++
+void TMyApp::CmSelectWindowLayout()
+{
+  try
+  {
+    TWindowLayout layout;
+    TWindowLayoutSelectionDlg dlg(GetMainWindow(), layout);
+    if (dlg.Execute() == IDOK)
+      RestoreWindowLayout(layout);
+  }
+  catch (const std::runtime_exception&amp;amp;)
+  {
+    FlushQueue(); // Remove any pending WM_QUIT message.
+    GetMainWindow()-&amp;gt;EnableWindow(true);
+    GetMainWindow()-&amp;gt;MessageBox("Something went wrong. Let's ignore it and hope for the best.");
+  }
+}
+~~~
+
+Note that calling FlushQueue may cause your application to miss important messages. A more robust solution is to manually remove only WM_QUIT:
+
+~~~
+:::C++
+  catch (const std::runtime_exception&amp;amp;)
+  {
+    const auto cancelQuit = [&amp;amp;]
+      {
+      for (auto m = MSG{}; ::PeekMessage(&amp;amp;m, nullptr, 0, 0, PM_REMOVE); ProcessMsg(m))
+        if (m.message == WM_QUIT)
+          return true;
+      return false;
+      };
+    const auto didCancelQuit = cancelQuit();
+    WARN(didCancelQuit, "Cancelled WM_QUIT message caused by unhandled exception");    
+    GetMainWindow()-&amp;gt;EnableWindow(true);
+    GetMainWindow()-&amp;gt;MessageBox("Something went wrong. Let's ignore it and hope for the best.");
+  }
+~~~
+
+But now things are starting to get complicated. Perhaps it is better to just let unhandled exceptions through. If you really need handling like this, then consider encapsulating it in an error handling function.
 &lt;br/&gt;

 &lt;hr/&gt;
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Tue, 14 Jan 2020 18:01:36 -0000</pubDate><guid>https://sourceforge.net4a53b397a57467f52066177156252febc6176d30</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v24
+++ v25
@@ -103,7 +103,7 @@
   c.CloseClipboard();
 ~~~

-Unfortunately, this  code will leak the global memory allocated by GlobalAlloc, if any preceding function call throws an exception before the SetCliboardData call takes ownership of the handle. It is also brittle with regard to the lock it acquires by calling GlobalLock. Although there is no intervening code that can throw exceptions between the acquisition and return of the lock (`memcpy_s` does not throw exceptions), this may change over time as the code is maintained. For example, a reckless programmer (probably yourself) may later add a C++ function call, say `SaveToLog`, that may throw exceptions.
+Unfortunately, this  code will leak the global memory allocated by GlobalAlloc, if any following function call throws an exception before the SetCliboardData call takes ownership of the handle. It is also brittle with regard to the lock it acquires by calling GlobalLock. Although there is no intervening code that can throw exceptions between the acquisition and return of the lock (`memcpy_s` does not throw exceptions), this may change over time as the code is maintained. For example, a reckless programmer (probably yourself) may later add a C++ function call, say `SaveToLog`, that may throw exceptions.

 ~~~
 :::C++
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Sat, 24 Nov 2018 21:52:52 -0000</pubDate><guid>https://sourceforge.net0fc86b475a2bdda0a10cd4063ea9f336a6a2dcde</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v23
+++ v24
@@ -109,7 +109,7 @@
 :::C++
   const auto buf = GlobalLock(h); CHECK(buf);
   memcpy_s(buf, bufSize, s.c_str(), bufSize);
-  SaveToLog(_T("Pasted to clipboard: "), static_cast&amp;lt;LPCTSTR&amp;gt;(buf)); // *** BIG PROBLEM! MAY THROW! ***
+  SaveToLog(_T("Copied to clipboard: "), static_cast&amp;lt;LPCTSTR&amp;gt;(buf)); // *** BIG PROBLEM! MAY THROW! ***
   GlobalUnlock(h);
 ~~~

&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Fri, 16 Mar 2018 14:58:58 -0000</pubDate><guid>https://sourceforge.netee7ecb0db4702b288477fb5485039929d61daf45</guid></item><item><title>Exceptions_and_OWLNext modified by Vidar Hasfjord</title><link>https://sourceforge.net/p/owlnext/wiki/Exceptions_and_OWLNext/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v22
+++ v23
@@ -73,7 +73,7 @@
 If your catch block is located inside a Windows API callback, from which you cannot let any exception escape, you can call [TApplication::SuspendThrow](http://owlnext.sourceforge.net/help/html/dd/dfb/classowl_1_1_t_application.html#a7f106330fe650a91ed8656e5a7873994) rather than rethrowing the TDiagException. If your code instigated the callback, then insert a call to [TApplication::ResumeThrow](http://owlnext.sourceforge.net/help/html/dd/dfb/classowl_1_1_t_application.html#a350888023df6969a3bf5eaf51cd148b3) after the instigating call. If using SuspendThrow and ResumeThrow is not feasible, then report or log the error and immediately shut down the application.
 &lt;br/&gt;

-&lt;br/&gt;
+&lt;hr/&gt;
 ## Expect an exception — write exception-safe code

 Unlike Windows API C code, OWLNext is C++ code, and you should expect that any function and constructor may throw an exception, unless it is explicitly stated in the API that it does not (i.e. the function signature has `noexcept` applied, or the now deprecated `throw()` specification). Unfortunately, as OWLNext is a thin wrapper for the Windows API, many programmers copy-and-paste code from the Windows documentation into their programs, code that is not written for exception safety. In particular, this becomes a big problem with functions that allocate resources, such as memory, GDI objects and file handles. Since an exception may occur, resources may leak, unless you carefully write your program to clean up, either by explicit exception handlers, or much more smartly, by using C++ code constructs, such as smart pointers, that exploit [RAII](http://en.cppreference.com/w/cpp/language/raii) to deallocate resources automatically.
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Vidar Hasfjord</dc:creator><pubDate>Fri, 16 Mar 2018 12:54:25 -0000</pubDate><guid>https://sourceforge.neteb2aa25e75a396214e3ff0e88f106333967c34ad</guid></item></channel></rss>