Topic: Any ideas for global catch handlers ?


Author: iv1net <iv1net@comcast.net>
Date: Mon, 24 Apr 2006 12:17:00 CST
Raw View
Timothy Madden wrote:
> Hello
>
> I am trying to write exception-safe applications, and a big problem is
> when I write any construct that throws or can throw.
>
> My compiler, as any good compiler, treats hardware exceptions as C++
> exceptions whose type you can not know, so in a practical sense I may
> say any constructor I write can potentialy throw.
>
> The problem is users of my class should be able to define global objects
> and if the constructor for a global object throws (with no try/catch
> inside) terminate is called. However if a local object is created then I
> do want to throw and I would not try/catch in the constructor.
>
> The same applies to expressions used in definitions for
> dynamicaly-initialised objects, be they POD or not.
>
> Anyone else thinks a set of global catch handlers can be usefull in
> real-life programming ?
>
> Somethingk like this:
>
> /* File Sync.cpp */
> #include "Sync.h"
> #include <threads.h>    // From some OS or third-party library
>
> HANDLE hSemaphore = CreateSemaphore();
> void ThreadProc();    // Uses hSemaphore
>
> HANDLE hThread =
>     hSemaphore
>         ?
>     (throw "Error creating semaphore.", NULL)
>         :
>     CreateThread(ThreadProc);
>
> // Gloabl catch handlers
> catch(LPCTSTR szErrorMessage)
> {
>     puts(seErrorMessage);
>     puts("Terminated");
> }
> catch(...)
> {
>     puts("Internal application error.");
>     puts("Terminated");
> }
>
> Of course, global handlers should only be used/allowed in the main
> application and not in a library. The matching of exception arguments
> with declard catch hanlder parameters is guaranted the be performed in
> the order handlers are encountered in the translation unit, but only
> among handlers in the same translation unit. It is also guaranted that
> handlers are searched in one translation unit at a time (for a match
> with the type of the exception).
>
> It would be also nice to have some handlers active on startup and others
> active on termination, or some language-defined way to say if app is
> currently starting or terminating (or a standard library defined way).
>
> Such global catch handlers are active and valid upon start-up over all
> translation units, not only the one where they are defined.
>
> If there are two handlers for the same exception type (in different
> units) it is implementation-defined (or even unspecified) which one will
> handle the exception. Not sure yet how things should be with handlers
> for types with a common signature, in case exception type is of the most
> derived type (if I may say so). Maybe implementors have an effisient way
> to spot handlers for most derived type, over the entire application.
>
> Of course it would be nice to have the handlers active even while
> program is running, in case an exception is not handled even out of main.
>
> I think one cound come up with many good ideas aroud this issue, but I
> would like to know if you think such global handlers are possible to
> introduce in the language end eventualy implement.
>
> Thank you
> Timothy Madden
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]
>
To do that over all translation units would imply that all compiled code
that has throwable events that could be mapped would be mapped to your
global set of exception handlers. In effect your are need a "compiler
event Interupt or IRQ" that is thrown and when a instatiated class
object throws it it generates the IRQ (software IRQ mapped to your
Global interup class) and that interrup saves the stack like any IRQ can
calls into your global interrupt handler (your global irq based ones)
This would require the compiler to emit code that did this or somethign
like it that mapped GLOBAL type public (exception class) to every class
that objects have throwable events.. I do not know but a compiler switch
may exist to map such things to somekind of DEFS.. If not maybe you
could create a public class and write your code as sub-friend classes of
this class and since it is part of the same encapsulation you could call
up to it in any of your code... like a super class over all your code
that handles any of the errors for any of the child classes...
Good Luck...iv1net

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Mon, 17 Apr 2006 09:50:31 CST
Raw View
Timothy Madden wrote:
> Hello
>
> I am trying to write exception-safe applications, and a big problem is
> when I write any construct that throws or can throw.
>
> My compiler, as any good compiler, treats hardware exceptions as C++
> exceptions whose type you can not know, so in a practical sense I may
> say any constructor I write can potentialy throw.
>
> The problem is users of my class should be able to define global objects
> and if the constructor for a global object throws (with no try/catch
> inside) terminate is called. However if a local object is created then I
> do want to throw and I would not try/catch in the constructor.
>
> The same applies to expressions used in definitions for
> dynamicaly-initialised objects, be they POD or not.
>
> Anyone else thinks a set of global catch handlers can be usefull in
> real-life programming ?
>
> Somethingk like this:
>
> /* File Sync.cpp */
> #include "Sync.h"
> #include <threads.h> // From some OS or third-party library
>
> HANDLE hSemaphore = CreateSemaphore();
> void ThreadProc(); // Uses hSemaphore
>
> HANDLE hThread =
>  hSemaphore
>   ?
>  (throw "Error creating semaphore.", NULL)
>   :
>  CreateThread(ThreadProc);
>
> // Gloabl catch handlers
> catch(LPCTSTR szErrorMessage)
> {
>  puts(seErrorMessage);
>  puts("Terminated");
> }
> catch(...)
> {
>  puts("Internal application error.");
>  puts("Terminated");
> }
>
It would be probably complex (but possible) to specify.
But, I think that there are clean workarounds:

Assuming there are a lot of global variables in a translation unit, you
should put them in a struct or class, and handle initialization like
that:

struct TThreadStuff
{
HANDLE hSemaphore;
HANDLE hThread;
TThreadStuff();
};

TThreadStuff::TThreadStuff() try
  :hSemaphore(CreateSemaphore())
  ,hThread(hSemaphore?(throw "Error creating semaphore.",
NULL):CreateThread(ThreadProc))
  {}
 catch(LPCTSTR szErrorMessage)
 {
  puts(seErrorMessage);
  puts("Terminated");
 }
 catch(...)
 {
  puts("Internal application error.");
  puts("Terminated");
 }
TThreadStuff ThreadStuff;

The above code is the "exact" translation of your code.
A more advanced technique would be a singleton class, or at least,
defining ThreadStuff as a static data member of TThreadStuff, and
define a private constructor in TThreadStuff.

Note that you can't recover from a global constructor's exception.
Because if ever you could recovered from, the object would not be
constructed, and when your program would exit, the destructor would be
called on a non-initialized object.
So, you can just log the error properly. You can't do more.

Anyway, when you know that a global variable is not vital to your
program and you want to recover from an exception, there is a solution.
"Any problem can be resolved by adding a level of indirection"

Simply write a "smart pointer":

template <class T>
class recoverable_ptr
{
T* p;
public:
recoverable_ptr() throw()
{
try
  {
  p=new T;
  }
catch(...)
  {
  p=NULL;
  }
}
T& operator *() const throw() {return p;}

// other members such as operator-> if you wish.
};

It is really powerful.
And, if order of initialization doesn't matter, you can put the
initialization code into operator*.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Timothy Madden <terminatorul@gmail.com>
Date: Mon, 17 Apr 2006 12:56:57 CST
Raw View
SuperKoko wrote:
> Timothy Madden wrote:
[...]
>>The problem is users of my class should be able to define global objects
>>and if the constructor for a global object throws (with no try/catch
>>inside) terminate is called. However if a local object is created then I
>>do want to throw and I would not try/catch in the constructor.
>>
>>The same applies to expressions used in definitions for
>>dynamicaly-initialised objects, be they POD or not.
>>
>>Anyone else thinks a set of global catch handlers can be usefull in
>>real-life programming ?
[...]
> Note that you can't recover from a global constructor's exception.
> Because if ever you could recovered from, the object would not be
> constructed, and when your program would exit, the destructor would be
> called on a non-initialized object.
> So, you can just log the error properly. You can't do more.
>
[...]

Yes, I can only fallback after an exception thrown while initializing a
global object.

My wish is for my app to degrade gracefully, and possibly exit with
EXIT_FAILURE, in face of any thrown (or even any hardware-generated)
exception (without having to write two versions, global and local, for
each of my classes). As a developer, one of the worse things that can
happen to me is for my app to crash. I would rather try/catch at my best
and display a message before exit, possibly with some context error
message taken from the OS or a library.

If my platform exposes CreateFile function to me, that can either return
an opened file or an error, then I want to be able to wrap it in a File
class, and throw some exception if CreateFile returns with an error.
Then I want clients of my new File class to use it freely, without the
restriction that they can instantiate class File only inside a block.

What I am doing currently is write two versions for my classes: one
version with explicit contruction and destruction, and one with normal
constructors and destructors. Any translation unit will have to use the
explicit version for objects outside any block and then initialize all
object inside some Init() function, local to the translation unit,
called as part of dynamic initialization for some POD data, and the Init
function could then try/catch around all exlicit calls for construction.
Quite ugly.

It would be interesting for a global catch handler to be able to return
an int, and if return is omitted, then 'return EXIT_FAILURE' would be
implied (like in main(), but with 'EXIT_FAILURE' instead of 0).

Timothy Madden

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: 17 Apr 2006 21:40:13 GMT
Raw View
Timothy Madden wrote:
> My wish is for my app to degrade gracefully, and possibly exit with
> EXIT_FAILURE, in face of any thrown (or even any hardware-generated)
> exception (without having to write two versions, global and local, for
> each of my classes). As a developer, one of the worse things that can
> happen to me is for my app to crash. I would rather try/catch at my best
> and display a message before exit, possibly with some context error
> message taken from the OS or a library.
>
> If my platform exposes CreateFile function to me, that can either return
> an opened file or an error, then I want to be able to wrap it in a File
> class, and throw some exception if CreateFile returns with an error.
> Then I want clients of my new File class to use it freely, without the
> restriction that they can instantiate class File only inside a block.
>
> What I am doing currently is write two versions for my classes: one
> version with explicit contruction and destruction, and one with normal
> constructors and destructors. Any translation unit will have to use the
> explicit version for objects outside any block and then initialize all
> object inside some Init() function, local to the translation unit,
> called as part of dynamic initialization for some POD data, and the Init
> function could then try/catch around all exlicit calls for construction.
> Quite ugly.
>
> It would be interesting for a global catch handler to be able to return
> an int, and if return is omitted, then 'return EXIT_FAILURE' would be
> implied (like in main(), but with 'EXIT_FAILURE' instead of 0).

Why not:

namespace // anonymous namespace... this function & data is private to
the initializing module.
{
std::auto_ptr<TypeThatCanThrow> InitializeAndCheckExceptions()
{
try
  {
  return new TypeThatCanThrow;
  }
catch(...)
  {
  // log information
  }
}

// auto_ptr construction and copy-assignment can't throw (ownership
transfer).
std::auto_ptr<TypeThatCanThrow> GlobalVariableAutoPointer =
InitializeAndCheckExceptions();
}

TypeThatCanThrow& GlobalVariable=*GlobalVariableAutoPointer;

IMHO, this workaround is fine.
There are many other workarounds you can experiment.
Use the one you like the most.
For example, you can have a centralized initialization if you wish:

namespace
{
std::auto_ptr<Type1> ptrGlobalVariable1;
std::auto_ptr<Type2> ptrGlobalVariable2;

bool InitializeAll()
{
  try
  {
    ptrGlobalVariable1=new Type1;
    ptrGlobalVariable2=new Type2;
  }
  catch(const ExceptionType1&)
  {
    // code here
  }
  catch(...)
  {
    // code here
  }
  return true;
}

bool InitializationOk=InitializeAll(); // returns true... or terminates
the program.
}
// definition of global variables:
Type1& GlobalVariable1=*ptrGlobalVariable1;
Type2& GlobalVariable2=*ptrGlobalVariable2;

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: 18 Apr 2006 03:00:49 GMT
Raw View
Timothy Madden wrote:
> Hello
>
> I am trying to write exception-safe applications, and a big problem is
> when I write any construct that throws or can throw.
>
> My compiler, as any good compiler, treats hardware exceptions as C++
> exceptions whose type you can not know, so in a practical sense I may
> say any constructor I write can potentialy throw.
>
> The problem is users of my class should be able to define global objects
> and if the constructor for a global object throws (with no try/catch
> inside) terminate is called. However if a local object is created then I
> do want to throw and I would not try/catch in the constructor.
>
> The same applies to expressions used in definitions for
> dynamicaly-initialised objects, be they POD or not.
>
> Anyone else thinks a set of global catch handlers can be usefull in
> real-life programming ?
>
> Somethingk like this:
>
> /* File Sync.cpp */
> #include "Sync.h"
> #include <threads.h> // From some OS or third-party library
>
> HANDLE hSemaphore = CreateSemaphore();
> void ThreadProc(); // Uses hSemaphore
>
> HANDLE hThread =
>  hSemaphore
>   ?
>  (throw "Error creating semaphore.", NULL)
>   :
>  CreateThread(ThreadProc);
>
> // Gloabl catch handlers
> catch(LPCTSTR szErrorMessage)
> {
>  puts(seErrorMessage);
>  puts("Terminated");
> }
> catch(...)
> {
>  puts("Internal application error.");
>  puts("Terminated");
> }
>
It would be probably complex (but possible) to specify.
But, I think that there are clean workarounds:

Assuming there are a lot of global variables in a translation unit, you
should put them in a struct or class, and handle initialization like
that:

struct TThreadStuff
{
HANDLE hSemaphore;
HANDLE hThread;
TThreadStuff();
};

TThreadStuff::TThreadStuff() try
  :hSemaphore(CreateSemaphore())
  ,hThread(hSemaphore?(throw "Error creating semaphore.",
NULL):CreateThread(ThreadProc))
  {}
 catch(LPCTSTR szErrorMessage)
 {
  puts(seErrorMessage);
  puts("Terminated");
 }
 catch(...)
 {
  puts("Internal application error.");
  puts("Terminated");
 }
TThreadStuff ThreadStuff;

The above code is the "exact" translation of your code.
A more advanced technique would be a singleton class, or at least,
defining ThreadStuff as a static data member of TThreadStuff, and
define a private constructor in TThreadStuff.

Note that you can't recover from a global constructor's exception.
Because if ever you could recovered from, the object would not be
constructed, and when your program would exit, the destructor would be
called on a non-initialized object.
So, you can just log the error properly. You can't do more.

Anyway, when you know that a global variable is not vital to your
program and you want to recover from an exception, there is a solution.
"Any problem can be resolved by adding a level of indirection"

Simply write a "smart pointer":

template <class T>
class recoverable_ptr
{
T* p;
public:
recoverable_ptr() throw()
{
try
  {
  p=new T;
  }
catch(...)
  {
  p=NULL;
  }
}
T& operator *() const throw() {return p;}
~recoverable_ptr()
{
delete p;
}

// other members such as operator-> if you wish.
};

It is really powerful.
And, if order of initialization doesn't matter, you can put the
initialization code into operator*.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 18 Apr 2006 14:56:13 GMT
Raw View
Timothy Madden ha scritto:
>
> My compiler, as any good compiler, treats hardware exceptions as C++
> exceptions whose type you can not know, so in a practical sense I may
> say any constructor I write can potentialy throw.

I don't agree with the "as any good compiler". C++ compilers are *not*
required to treat hardware exceptions as C++ exceptions. In fact doing
so comes at a cost that a programmer may not be willing to pay. That's
because the compiler can always detect in advance where a C++ exception
may be thrown (that is: only at throw expression), while a hardware
exception may be thrown at any point, even in the middle of an assembler
instruction sequence that performs some task that is perceived as
"atomic" in C++ ("atomic" in the sense that it can't be logically
decomposed further, not to be confused with threading issues). This
difference requires the compiler to keep track of some implementation
details that would not otherwise be needed and so may result in
suboptimal code. Moreover, there are very few hardware exception that
are worth catching. Most of the times, if an hardware exception is
thrown, the CPU state is screwed up to a point that the problem is
already unrecoverable (think about stack overflow, for example).
So, my personal opinion is that the compiler should *not* treat hardware
exception as C++ exception, or at least make such treatment optional.

> The problem is users of my class should be able to define global objects
> and if the constructor for a global object throws (with no try/catch
> inside) terminate is called. However if a local object is created then I
> do want to throw and I would not try/catch in the constructor.

The problem is: if the constructor of a global throws, what can you do?
Execution can't continue nicely, because a global object can't be left
in an undetermined state. The only thing you can reasonably do is to
provide the user with some diagnostic and a clean exit. This "benefit"
is very little compared to cost of designing a new language feature to
get it, so, while interesting, C++ has much more important missing
features that we have to consider first.

Notice that an exception thrown during the construction of a global
object most of the times hides a logic error, so where's the need of
pretty diagnostic messages? However, there are cases where a constructor
can reasonably throw for other reason at runtime. In that case, if a
diagnostic to the user is required, I always prefer the singleton
pattern to plain global objects.

Just my opinion,

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "ThosRTanner" <ttanner2@bloomberg.net>
Date: 19 Apr 2006 16:30:06 GMT
Raw View
Timothy Madden wrote:
> Hello
>
> I am trying to write exception-safe applications, and a big problem is
> when I write any construct that throws or can throw.
>
> My compiler, as any good compiler, treats hardware exceptions as C++
> exceptions whose type you can not know, so in a practical sense I may
> say any constructor I write can potentialy throw.
Is that a troll? It's big, green, and...

> The problem is users of my class should be able to define global objects
> and if the constructor for a global object throws (with no try/catch
> inside) terminate is called. However if a local object is created then I
> do want to throw and I would not try/catch in the constructor.
>
> The same applies to expressions used in definitions for
> dynamicaly-initialised objects, be they POD or not.
>
> Anyone else thinks a set of global catch handlers can be usefull in
> real-life programming ?
>
> Somethingk like this:
>
> /* File Sync.cpp */
> #include "Sync.h"
> #include <threads.h> // From some OS or third-party library
>
> HANDLE hSemaphore = CreateSemaphore();
> void ThreadProc(); // Uses hSemaphore
>
> HANDLE hThread =
>  hSemaphore
>   ?
>  (throw "Error creating semaphore.", NULL)
>   :
>  CreateThread(ThreadProc);
>
> // Gloabl catch handlers
> catch(LPCTSTR szErrorMessage)
> {
>  puts(seErrorMessage);
>  puts("Terminated");
> }
> catch(...)
> {
>  puts("Internal application error.");
>  puts("Terminated");
> }
I think that is horribly unsafe. You're going to have all sorts of
order-of-initialisation problems if you do that. It's C++, so most
people would be tempted to use cout and cerr - and it would probably
work sometimes on some implementations.

> Of course, global handlers should only be used/allowed in the main
> application and not in a library. The matching of exception arguments
> with declard catch hanlder parameters is guaranted the be performed in
> the order handlers are encountered in the translation unit, but only
> among handlers in the same translation unit. It is also guaranted that
> handlers are searched in one translation unit at a time (for a match
> with the type of the exception).
Sorry, I find this confusing. Do you mean that only the handlers
declared in the same TU as main will be allowed? What if I want to put
the code into a library or a dll? - Well, actually, I suppose you
couldn't put it in a dll, because of ordering problems. But I don't
know how the compiler would tell, unless the requirement was for the
global handlers to be in the same TU as main - and I know of nothing
that stops you putting main in a dll.

> It would be also nice to have some handlers active on startup and others
> active on termination, or some language-defined way to say if app is
> currently starting or terminating (or a standard library defined way).
It might not be a bad idea for exit to set a flag saying "exit in
progress", but I'd not sure how you'd register an exception handler for
that, apart from ensuring that exit only ever gets called from one
place, and coding it as
try { exit(0) } catch (handler1 const &)....

> Such global catch handlers are active and valid upon start-up over all
> translation units, not only the one where they are defined.
>
> If there are two handlers for the same exception type (in different
> units) it is implementation-defined (or even unspecified) which one will
> handle the exception. Not sure yet how things should be with handlers
> for types with a common signature, in case exception type is of the most
> derived type (if I may say so). Maybe implementors have an effisient way
> to spot handlers for most derived type, over the entire application.
Link error?

> Of course it would be nice to have the handlers active even while
> program is running, in case an exception is not handled even out of main.
Whilst I agree that the current handling of some systems for
int main() { throw std::runtime_error("Help"); } is less than perfect,
I'm not sure that this structure you are imposing is helpful.

> I think one cound come up with many good ideas aroud this issue, but I
> would like to know if you think such global handlers are possible to
> introduce in the language end eventualy implement.

You might want to consider a registry with which you register your
"exception handling" code and code main as something like

int main()
{
    try
    {
    }
    catch (my_exception_base const &e)
    {
        lookup type id of e in registry
        call returned handler with e
   }
}

Similarly, for your global initialisation, it may be better for all
your global data to consist of a class which merely registers itself
with an initialisation registry. Then main gets every class from the
initialisation registry and calls the initialiser code. Then any
exceptions from there are thrown in the context of main, which can do
something with them.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Timothy Madden <terminatorul@gmail.com>
Date: Thu, 20 Apr 2006 10:17:04 CST
Raw View
ThosRTanner wrote:
> Timothy Madden wrote:
[...]
>>Somethingk like this:
>>
>>/* File Sync.cpp */
>>#include "Sync.h"
>>#include <threads.h> // From some OS or third-party library
>>
>>HANDLE hSemaphore = CreateSemaphore();
>>void ThreadProc(); // Uses hSemaphore
>>
>>HANDLE hThread =
>> hSemaphore
>>  ?
>> (throw "Error creating semaphore.", NULL)
>>  :
>> CreateThread(ThreadProc);
>>
>>// Gloabl catch handlers
>>catch(LPCTSTR szErrorMessage)
>>{
>> puts(seErrorMessage);
>> puts("Terminated");
>>}
>>catch(...)
>>{
>> puts("Internal application error.");
>> puts("Terminated");
>>}
>
> I think that is horribly unsafe. You're going to have all sorts of
> order-of-initialisation problems if you do that.

What order of initialisation problems (apart form global catch handlers) ?

Maybe you are worried about a thread being started before main is
entered. Well, that would be my problem, not a language problem. Maybe
thread is using only data defined in the same TU, before hSemaphore and
hThread. As long as I know what I am doing, it is legal and well-formed.

Or maybe you are worried about stdout not being initilised yet in the
global catch handlers, for puts to work. I this case, too, I think it
should be.

>
>
>>Of course, global handlers should only be used/allowed in the main
>>application and not in a library. The matching of exception arguments
>>with declard catch hanlder parameters is guaranted the be performed in
>>the order handlers are encountered in the translation unit, but only
>>among handlers in the same translation unit. It is also guaranted that
>>handlers are searched in one translation unit at a time (for a match
>>with the type of the exception).
>
> Sorry, I find this confusing. Do you mean that only the handlers
> declared in the same TU as main will be allowed? What if I want to put
> the code into a library or a dll? - Well, actually, I suppose you
> couldn't put it in a dll, because of ordering problems. But I don't
> know how the compiler would tell, unless the requirement was for the
> global handlers to be in the same TU as main - and I know of nothing
> that stops you putting main in a dll.

What ordering problems ?
Only the implementation choses order for initialisation of translation
units, and any transalation unit is allowed to be initialised even late
after main has been entered (but before data in the translation unit is
used).

A language feature to allow programmers to explicitly request
initialization of a given translation unit would also be great. Having
two or more translation units that depend on each other would be a
runtime error (would throw some language-support exception). Something like:

/* Library header Moon.h */

extern fstream MoonLogFile;

//Acces point for explicit initialiser
extern virtual typename Initializer InitMoon;


/* Moon library implementation.
    Moon.cpp */
#include <fstream>
#include "Moon.h"

fstream MoonLogFile("MoonLog.txt");

// If invoked outside TU will trigger TU initialisation
virtual typename Initializer InitMoon;     // definition for InitMoon


/* Main application file.
    MoonApplication.cpp */
#include <fstream>
#include "Moon.h"

// Invoke initializer for Moon
// This is not an ordinary function call, but a new language feature
InitMoon();

// Now Moon is guaranted to be initialized, and MoonLogFile can be used
bool fInitalMessage =
 (
   MoonLogFile << "Moon application is now starting"
     <<
   endl,
   true
 );

int main(int argc, char *argv[])
{
    while (arg)
   {
     argc--;
     MoonLogFile << "argv[argc] << endl;
   }
}

I used the syntax 'virtual typename Initializer' to indicate that the
declared entity InitMoon represents some new type of entity in the
language (not a declaration for an object, type, function, etc.)

>
>>It would be also nice to have some handlers active on startup and others
>>active on termination, or some language-defined way to say if app is
>>currently starting or terminating (or a standard library defined way).
>
> It might not be a bad idea for exit to set a flag saying "exit in
> progress", but I'd not sure how you'd register an exception handler for
> that, apart from ensuring that exit only ever gets called from one
> place, and coding it as
> try { exit(0) } catch (handler1 const &)....

I don't think that will work. You are not supposed to return from exit,
and I think exit will call terminate even if used inside a try block.

What should happen after the handler 'catch (handler1 const &)...' is
executed ?

>
>>Such global catch handlers are active and valid upon start-up over all
>>translation units, not only the one where they are defined.
>>
>>If there are two handlers for the same exception type (in different
>>units) it is implementation-defined (or even unspecified) which one will
>>handle the exception. Not sure yet how things should be with handlers
>>for types with a common signature, in case exception type is of the most
>>derived type (if I may say so). Maybe implementors have an effisient way
>>to spot handlers for most derived type, over the entire application.
>
> Link error?

Well, for class types in the same inheritance hierarchy, a linker error
is not appropriate. I think implementations should allow a minimum level
of support so that programmers can catch both std::exception and
std::runtime_error, even in different TU.

With handlers for the same exception type a linker error might be
considered as an option, but I'm afraid this option not to be too
restrictive, so I opt for implementation-defined/unspecified.

Timothy Madden
Romania

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: terminatorul@gmail.com (Timothy Madden)
Date: Sun, 16 Apr 2006 16:56:55 GMT
Raw View
Hello

I am trying to write exception-safe applications, and a big problem is
when I write any construct that throws or can throw.

My compiler, as any good compiler, treats hardware exceptions as C++
exceptions whose type you can not know, so in a practical sense I may
say any constructor I write can potentialy throw.

The problem is users of my class should be able to define global objects
and if the constructor for a global object throws (with no try/catch
inside) terminate is called. However if a local object is created then I
do want to throw and I would not try/catch in the constructor.

The same applies to expressions used in definitions for
dynamicaly-initialised objects, be they POD or not.

Anyone else thinks a set of global catch handlers can be usefull in
real-life programming ?

Somethingk like this:

/* File Sync.cpp */
#include "Sync.h"
#include <threads.h> // From some OS or third-party library

HANDLE hSemaphore = CreateSemaphore();
void ThreadProc(); // Uses hSemaphore

HANDLE hThread =
 hSemaphore
  ?
 (throw "Error creating semaphore.", NULL)
  :
 CreateThread(ThreadProc);

// Gloabl catch handlers
catch(LPCTSTR szErrorMessage)
{
 puts(seErrorMessage);
 puts("Terminated");
}
catch(...)
{
 puts("Internal application error.");
 puts("Terminated");
}

Of course, global handlers should only be used/allowed in the main
application and not in a library. The matching of exception arguments
with declard catch hanlder parameters is guaranted the be performed in
the order handlers are encountered in the translation unit, but only
among handlers in the same translation unit. It is also guaranted that
handlers are searched in one translation unit at a time (for a match
with the type of the exception).

It would be also nice to have some handlers active on startup and others
active on termination, or some language-defined way to say if app is
currently starting or terminating (or a standard library defined way).

Such global catch handlers are active and valid upon start-up over all
translation units, not only the one where they are defined.

If there are two handlers for the same exception type (in different
units) it is implementation-defined (or even unspecified) which one will
handle the exception. Not sure yet how things should be with handlers
for types with a common signature, in case exception type is of the most
derived type (if I may say so). Maybe implementors have an effisient way
to spot handlers for most derived type, over the entire application.

Of course it would be nice to have the handlers active even while
program is running, in case an exception is not handled even out of main.

I think one cound come up with many good ideas aroud this issue, but I
would like to know if you think such global handlers are possible to
introduce in the language end eventualy implement.

Thank you
Timothy Madden

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]