diff --git a/doc/BOOST_THROW_EXCEPTION.html b/doc/BOOST_THROW_EXCEPTION.html index 89395fb..7d8806f 100644 --- a/doc/BOOST_THROW_EXCEPTION.html +++ b/doc/BOOST_THROW_EXCEPTION.html @@ -27,15 +27,15 @@ #include <boost/current_function.hpp> #define BOOST_THROW_EXCEPTION(x)\ ::boost::throw_exception( ::boost::enable_error_info(x) <<\ - ::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\ + ::boost::throw_function(BOOST_THROW_EXCEPTION_CURRENT_FUNCTION) <<\ ::boost::throw_file(__FILE__) <<\ ::boost::throw_line((int)__LINE__) ) #else #define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x) #endif -
This macro takes an exception object, records BOOST_CURRENT_FUNCTION, __FILE__ and __LINE__ in it, and forwards it to throw_exception. To recover this information at the catch site, use get_error_info; the information is also included in the message returned by diagnostic_information.
+This macro takes an exception object, records the current function name, __FILE__ and __LINE__ in it, and forwards it to throw_exception. To recover this information at the catch site, use get_error_info; the information is also included in the message returned by diagnostic_information.
This header has been deprecated.
-Please #include <boost/exception/all.hpp> instead.
-Note that on some non-conformant compilers, for example MSVC 7.0 and older, as well as BCC, BOOST_EXCEPTION_DISABLE is implicitly defined in boost/throw_exception.hpp.
BOOST_NO_EXCEPTIONS
This macro disables exception handling in Boost, forwarding all exceptions to a user-defined non-template version of boost::throw_exception. However, unless BOOST_EXCEPTION_DISABLE is also defined, users can still examine the exception object for any data added at the point of the throw, or use boost::diagnostic_information (of course under BOOST_NO_EXCEPTIONS, the user-defined boost::throw_exception is not allowed to return to the caller.)
+BOOST_THROW_EXCEPTION_CURRENT_FUNCTION
+The BOOST_THROW_EXCEPTION macro uses BOOST_THROW_EXCEPTION_CURRENT_FUNCTION to record the name of the current function in the exception object. Unless overridden by the user, BOOST_THROW_EXCEPTION_CURRENT_FUNCTION expands to BOOST_CURRENT_FUNCTION.
A string value that contains varying amount of implementation-specific diagnostic information about the passed object:
-A string value that contains varying amount of diagnostic information about the passed object:
+The string representation of each error_info object is deduced by a function call that is bound at the time the error_info<Tag,T> template is instantiated. The following overload resolutions are attempted in order:
-The string representation of each error_info object is deduced by an unqualified call to to_string(x), where x is of type error_info<Tag,T>, for which Boost Exception defines a generic overload. It converts x.value() to string, attempting to bind (at the time the error_info<Tag,T> template is instantiated) the following functions in order:
+The first successfully bound function is used at the time diagnostic_information is called; if all 3 overload resolutions are unsuccessful, the system is unable to convert the error_info object to string, and an unspecified stub string value is used without issuing a compile error.
+The first successfully bound function is used at the time diagnostic_information is called; if both overload resolutions are unsuccessful, the system is unable to convert the error_info object to string, and an unspecified stub string value is used without issuing a compile error.
The exception_ptr overload of diagnostic_information is equivalent to:
if( p ) try @@ -53,14 +49,9 @@ boost } catch(...) { - return current_exception_diagnostic_information(); + return current_exception_diagnostic_information(verbose); } else return <unspecified-string-value>;-
this is a possible output from the diagnostic_information function, as used in libs/exception/example/example_io.cpp:
example_io.cpp(70): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) @@ -71,7 +62,7 @@ std::exception::what: example_io error [struct boost::errinfo_file_name_ *] = tmp1.txt [struct boost::errinfo_file_open_mode_ *] = rb
namespace boost { - char const * diagnostic_information_what( boost::exception const & e ) throw(); + char const * diagnostic_information_what( boost::exception const & e, bool verbose=true ) throw(); }
The diagnostic_information_what function is intended to be called from a user-defined std::exception::what() override. This allows diagnostic information to be returned as the what() string.
Instead of using the throw keyword directly, it is preferable to call boost::throw_exception. This is guaranteed to throw an exception that derives from boost::exception and supports the exception_ptr functionality.
Nothing.
To retrieve data from a boost::exception object, use the get_error_info function template.
An exception_ptr can be added as error_info to any boost::exception. This is a convenient way to nest exceptions. There is no limit on the depth of the nesting, however cyclic references result in undefined behavior.
The cost is that boost::exception is added as a base of the exception emitted by boost::throw_exception (unless the passed type already derives from boost::exception.)
+Calling boost::throw_exception does not cause dynamic memory allocations.
+In addition to calling boost::throw_exception, BOOST_THROW_EXCEPTION invokes __FILE__, __LINE__ and the BOOST_THROW_EXCEPTION_CURRENT_FUNCTION macros. The space required to store the information is already included in sizeof(boost::exception).
+Calling BOOST_THROW_EXCEPTION does not cause dynamic memory allocations.
+The benefit of calling boost::throw_exception instead of using throw directly is that it ensures that the emitted exception derives from boost::exception and that it is compatible with boost::current_exception.
+The BOOST_THROW_EXCEPTION macro also results in a call to boost::throw_exception, but in addition it records in the exception object the __FILE__ and __LINE__ of the throw, as well as the pretty name of the function that throws. This enables boost::diagnostic_information to compose a more useful, if not user-friendly message.
+Typical use of boost::diagnostic_information is:
+catch(...)
+ {
+ std::cerr <<
+ "Unexpected exception, diagnostic information follows:\n" <<
+ current_exception_diagnostic_information();
+ }
+This is a possible message it may display -- the information in the first line is only available if BOOST_THROW_EXCEPTION was used to throw:
+example_io.cpp(70): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) +Dynamic exception type: class boost::exception_detail::clone_impl<class fopen_error> +std::exception::what: example_io error +[struct boost::errinfo_api_function_ *] = fopen +[struct boost::errinfo_errno_ *] = 2, "No such file or directory" +[struct boost::errinfo_file_name_ *] = tmp1.txt +[struct boost::errinfo_file_open_mode_ *] = rb+
In some development environments, the first line in that message can be clicked to show the location of the throw in the debugger, so it's easy to set a break point and run again to see the unexpected throw in the context of its call stack.
Despite that virtual inheritance should be used in deriving from base exception types, many programmers fail to follow this principle when deriving from std::exception. If boost::exception derives from std::exception, using the enable_error_info function with such user-defined types would introduce dangerous ambiguity which would break all catch(std::exception &) statements.
-Of course, boost::exception should not be used to replace std::exception as a base type in exception type hierarchies. Instead, it should be included as a virtual base, in addition to std::exception (which should also be derived virtually.)
+Despite that virtual inheritance should be used in deriving from base exception types, quite often exception types (including the ones defined in the standard library) don't derive from std::exception virtually.
+If boost::exception derives from std::exception, using the enable_error_info function with such user-defined types would introduce dangerous ambiguity which would break all catch(std::exception &) statements.
+Of course, boost::exception should not be used to replace std::exception as a base type in exception type hierarchies. Instead, it should be included as a virtual base, in addition to std::exception (which should probably also be derived virtually.)
To prevent exception-neutral contexts from erroneously erasing the type of the original exception when adding error_info to an active exception object:
catch( boost::exception & e ) @@ -37,55 +63,16 @@ e << foo_info(foo); throw; //Okay, re-throwing the original exception object. }-
The space overhead for the boost::exception data members is negligible in the context of exception handling. Throwing objects that derive from boost::exception does not by itself cause dynamic memory allocations.
-Deriving from boost::exception enables any data to be added to exceptions, which usually does allocate memory. However, this memory is reclaimed when the exception has been handled, and since typically user code does not allocate memory during the unrolling of the stack, adding error info to exceptions should not cause memory fragmentation.
-The benefit of calling boost::throw_exception instead of using throw directly is that it ensures that the emitted exception derives from boost::exception and that it is compatible with boost::current_exception.
-The BOOST_THROW_EXCEPTION macro also results in a call to boost::throw_exception, but in addition it records in the exception object the __FILE__ and __LINE__ of the throw, as well as the pretty name of the function that throws. This has virtually no overhead, yet enables boost::diagnostic_information to compose a more useful, if not user-friendly message.
-Typical use of boost::diagnostic_information is:
-catch( boost::exception & e ) - { - std::cerr << "OMG!" << boost::diagnostic_information(e); - } -catch( ... ) - { - std::cerr << "OMG!!!"; - }-
This is a possible message it may display, the first line is only possible if BOOST_THROW_EXCEPTION is used:
-example_io.cpp(70): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) -Dynamic exception type: class boost::exception_detail::clone_impl<class fopen_error> -std::exception::what: example_io error -[struct boost::errinfo_api_function_ *] = fopen -[struct boost::errinfo_errno_ *] = 2, "No such file or directory" -[struct boost::errinfo_file_name_ *] = tmp1.txt -[struct boost::errinfo_file_open_mode_ *] = rb-
The boost::throw_exception function predates the Boost Exception library and there has been some concern about its current behavior of injecting boost::exception as a base of any exception passed to boost::throw_exception. Such concerns are dictated by the typical strict interpretation of a common principle in C and C++, that users only pay for features they actually use.
-The problem is that users of Boost Exception can't by themselves cause a library to throw types that derive from boost::exception, and without this they can't use any of the Boost Exception facilities.
-For example, if a user wants to use Boost Serialization in a separate thread, it is desirable to be able to transport exceptions emitted by that library into the main thread where they can be analyzed to generate a user-friendly message. This can be easily achieved using boost::exception_ptr, but this requires that Boost Serialization throws exceptions using boost::enable_current_exception. If Boost Serialization calls boost::throw_exception to throw, this behavior happens automatically and transparently.
-The cost of this integration is:
-Before throwing an object of type that derives from boost::exception, it is often desirable to add one or more error_info objects in it. The syntactic sugar provided by exception/operator<< allows this to be done directly in a throw expression:
+Before throwing an object of type that derives from boost::exception, it is often desirable to add one or more error_info objects in it. The syntactic sugar provided by operator<< allows this to be done directly in a throw expression:
throw error() << foo_info(foo) << bar_info(bar);-
which saves typing compared to this possible alternative:
-error e; -e.add(foo_info(foo)); -e.add(bar_info(bar)); -throw e;-
and looks better than something like:
-throw error().add(foo_info(foo)).add(bar_info(bar));
This question is referring to the following issue. Consider this throw statement example:
throw file_open_error() << file_name(fn);
The intention here is to throw a file_open_error, however if operator<< fails to copy the std::string contained in the file_name error_info wrapper, a std::bad_alloc could propagate instead. This behavior seems undesirable to some programmers.
Bjarne Stroustrup, The C++ Programming Language, 3rd Edition, page 371:
-"Throwing an exception requires an object to throw. A C++ implementation is required to have enough spare memory to be able to throw bad_alloc in case of memory exhaustion. However, it is possible that throwing some other exception will cause memory exhaustion."
So, an attempt to throw any exception may already result in propagating std::bad_alloc instead.
+Therefore, the language itself does not guarantee that an attempt to throw an exception is guaranteed to throw an object of the specified type; propagating a std::bad_alloc seems to be a possibility even outside of the scope of Boost Exception.
The interface of get_error_info may be affected by the build configuration macros.
E must derive publicly from std::exception.
-Under BOOST_NO_EXCEPTIONS, unless BOOST_EXCEPTION_DISABLE is also defined, users can examine the passed exception object using boost::get_error_info, or format an automatic diagnostic message using boost::diagnostic_information.
+E must derive publicly from std::exception. E may or may not derive from boost::exception.
+