This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
verbose terminate_handler
- From: Jason Merrill <jason at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org
- Date: Thu, 15 Nov 2001 13:30:00 +0000
- Subject: verbose terminate_handler
I just whipped this up for a customer who requested that a call to
terminate() print some information about the exception which caused it, as
apparently the SunPro C++ does. It prints the demangled name of the
exception type and, for objects derived from exception, the result of
what().
An awkward thing about this is that currently it needs to look in the
libsupc++ and gcc source directories for the EH unwinder headers. Another
problem is that __cxa_demangle isn't currently usable in general because
it's under the GPL.
My question is, how much of this should go into the distribution? I see
several (largely orthogonal) options:
1) Nothing. Let anyone who wants this functionality reinvent it
themselves. This is complicated by its reliance on ABI internals.
2) Install unwind-cxx.h and unwind.h so that users can get at them without
keeping GCC source trees around.
2) Add current_exception_type to libsupc++, perhaps to the ABI
specification. This would avoid the need to look at the unwinder
headers.
3) Add verbose_terminate_handler to libsupc++ or libstdc++ and document it;
people would still need to activate it with set_terminate.
Thoughts?
Jason
// verbose terminate_handler for IA64/GNU V3 C++ ABI
// Copyright (C) 2001 Red Hat, Inc.
#include <exception>
#include <stdlib.h>
#include <stdio.h>
#include <cxxabi.h>
// This file is found in the libstdc++-v3/libsupc++ source directory, and
// it includes unwind.h from the gcc source directory.
#include <unwind-cxx.h>
using namespace std;
using namespace abi;
// Returns the type_info for the currently handled exception [15.3/8], or
// null if there is none.
type_info *current_exception_type ()
{
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
if (header)
return header->exceptionType;
else
return 0;
}
void verbose_terminate_handler ()
{
// Make sure there was an exception; terminate is also called for an
// attempt to rethrow when there is no suitable exception.
type_info *t = current_exception_type ();
if (t)
{
char const *name = t->name ();
// Note that "name" is the mangled name.
{
int status;
// __cxa_demangle is currently disabled in cp-demangle.c, and
// subject to the GPL (Boo!).
char *dem = __cxa_demangle (name, 0, 0, &status);
printf ("terminate called after throwing a `%s'\n",
status == 0 ? dem : name);
if (status == 0)
free (dem);
}
// If the exception is derived from std::exception, we can give more
// information.
try { throw; }
catch (exception &exc) { printf (" what(): %s\n", exc.what()); }
catch (...) { }
}
else
printf ("terminate called without an active exception\n");
abort ();
}
// EXAMPLE -- cut here
#include <stdexcept>
int main ()
{
std::set_terminate (verbose_terminate_handler);
//throw;
//throw 1;
throw std::out_of_range ("not really");
}