I find out there are an obviously different behaviors between boost::packaged_task and std::packaged_task. I had tested the boost version 1.55 and 1.56, and the c++11 compilers are Visual Studio 2013 and gcc(in XCode).
That is, the calling get() of the future generated from packaged_task::get_future() emits different exceptions.
Here is my simple code:
#include <boost/thread/future.hpp>
#include <future>
#include <iostream>
struct my_error {};
void throw_something()
{
throw my_error();
}
int main()
{
typedef boost::packaged_task<void> packaged_task;
packaged_task task(throw_something);
auto fu = task.get_future();
task();
try {
fu.get();
std::cout << "no exception" << std::endl;
}
catch (const my_error&) {
std::cout << "catch my_error" << std::endl;
} catch (const std::exception &e) {
std::cout << "catch std::exception: " << e.what() << std::endl;
} catch (...) {
std::cout << "catch unknown error" << std::endl;
}
std::system("pause");
return 0;
}
In Visual Studio 2013 the result is: catch std::exception: Unknown exception
and in gcc(in XCode) is: catch std::exception: std::exception
But if I changed the type of packaged_task to c++11 provided by Visual Studio 2013 or gcc, that's:
typedef std::packaged_task<void()> packaged_task;
The result becomes difference: catch my_error
I think std::packaged_task works correctly because I can catch the really type. Do I misuse boost::packaged_task?
A key difference could be that the standard library packaged_task might be statically linked, and the boost::thread version is linked in dynamically.
Throwing exceptions across dynamic library boundaries may not always work, especially when the sources weren't compiled with exactly the same compiler options.
You could
check that the libraries were compiled with the same flags
use the static version of Boost Thread library (BOOST_THREAD_STATIC, BOOST_ALL_NO_LIB might be related from a quick a google), See also http://www.boost.org/boost-build2/doc/html/bbv2/tutorial/linkage.html
Related
In this simple use of C++ contracts, I get the error: no type named 'fail_fast' in namespace 'gsl'. Will try block throw the fast_fail exception or some other exception?
#define GSL_THROW_ON_CONTRACT_VIOLATION
#include <gsl/gsl>
#include <iostream>
int main(void)
{
try {
Expects(false);
}
catch(const gsl::fail_fast &e) {
std::cout << "exception: " << e.what() << '\n';
}
}
GSL_THROW_ON_CONTRACT_VIOLATION and gsl::fast_fail were removed from the Microsoft GSL starting with release v3.0.0. All contract violations result in a call to std::terminate unless you are building in kernel mode for MSVC where it invokes __fastfail.
Header file gsl_assert.h only defines gsl::fail_fast exception with GSL_THROW_ON_CONTRACT_VIOLATION defined. So it compiles now? – Serve Laurijssen
There was a period of time where gsl::fast_fail was defined only when GSL_THROW_ON_CONTRACT_VIOLATION was defined, however that was identified in #267 and subsequently fixed in #268.
I'm using the clang x64 compiler on MacOS 10.12. I have the following code:
try {
throw CryptoPP::Exception(CryptoPP::Exception::OTHER_ERROR, "test");
} catch(CryptoPP::Exception &e) {
std::cout << "cryptopp" << e.what() << std::endl;
} catch(std::exception &e) {
std::cout << "std" << e.what() << std::endl;
}
The CryptoPP is build as static library. When I use it in in a executable application, it works as expected.
It gets problematic when I use the CryptoPP static library in a dynamic library. Inside the library, I have that exact code (i.e. the exception does not leave the library). However, the log shows
std test
Meaning that only the second catch did actually catch the exception. How is that possible?
I have the following sample code that throws a std::ios_base::failure and tries to catch it, using clang 4.0 in c++11 mode:
#include <ios>
#include <iostream>
#include <stdexcept>
int
main()
{
try {
throw new std::ios_base::failure( "Bonkers" );
}
catch( std::ios_base::failure &e ) {
std::cout << "Failure " << e.what() << std::endl;
}
catch( ... ) {
std::cout << "Anything" << std::endl;
}
return 0;
}
I compile the program like this:
clang++-4.0 --std=c++11 -g -W -Wall ex.cc -o ex
And I get the output:
Anything
I would have expected for it to catch the specific exception. I tried the same with g++ 5.4, but the same result. Also tried without the c++11 flag, does not help either. Taking out the catch all clause gives me this:
terminate called after throwing an instance of 'std::ios_base::failure[abi:cxx11]*'
So what am I missing, and what can I do to fix this? The abi:cxx11 is also shown when I am NOT using the c++11 flag.
As mentioned in the comments, in C++ you do not need to allocate the exception via new and hence throw the pointer to the exception, as would be done in Java.
Instead you simply construct the exception and throw it:
throw std::ios_base::failure( "Bonkers" );
Then the types of the catch clause will match, and the program will behave as expected.
As we know, using boehm-gc in multi-thread requires calling GC_register_my_thread with stack base from GC_get_stack_base. but It seems not to work well with C++11's thread library, such as std::thread... How can I use boehm-gc with C++11's thread library?
(I use VS2013)
edit: This is tested code. std::thread is good, but std::future doesn't work (stop on _CrtIsValidHeapPointer
#include <iostream>
#include <thread>
#include <future>
#define GC_THREADS
#include <gc.h>
#include <gc_cpp.h>
#pragma comment(lib, "gcmt-lib")
void foo()
{
GC_stack_base sb;
GC_get_stack_base(&sb);
GC_register_my_thread(&sb);
int *ptr;
for (int i = 0; i < 10; i++)
{
ptr = new (GC) int;
*ptr = 1;
}
GC_unregister_my_thread();
}
int main()
{
GC_INIT();
GC_allow_register_threads();
std::cout << "test for std::thread";
std::thread thrd(foo);
thrd.join();
std::cout << " [sucs]\n";
std::cout << "test for std::future";
std::future<void> fu = std::async(std::launch::async, foo);
fu.get();
std::cout << " [sucs]\n";
std::cin.get();
}
edit: here is a capture of stack trace (Sorry that it isn't English, but I think it doesn't matter, anyway)
and here is a debug message
HEAP[TestGC.exe]: Invalid address specified to RtlValidateHeap( 00E80000, 00C92F80 )
While debugging, I found The error occurs after fu.get().
edit: The error doesn't occur with /MD(or /MDd)...
(I think GC might touch library's pointers (namespcae Concurrency), but it is just guess;;)
Before you start using the collector and before you create the threads make sure that you issue both
GC_INIT, and
GC_allow_register_threads
Then in every thread follow it up with,
GC_get_stack_base/GC_register_my_thread, and eventually
GC_unregister_my_thread.
You didn't say what you are compiling with but it works for gcc 4.8 (with -std=c++11).
EDIT: The OP was able to resolve the issue by addressing the instruction above and compiling the code with the /MD[d] flags for the multi-threaded dynamic MSVCR100 runtime. The issue remained unresolved for the multithreaded statically compiled runtime.
#include "iostream"
#include "conio.h"
#include "exception"
#include "cstdlib"
using namespace std;
void myunexpected ()
{
cerr << "unexpected called\n";
throw 0; // throws int (in exception-specification)
}
void myfunction () throw (int)
{
throw 'x'; // throws char (not in exception-specification)
}
int main (void)
{
set_unexpected (myunexpected);
try
{
myfunction();
}
catch (int) { cerr << "caught int\n"; }
catch (...) { cerr << "caught other exception (non-compliant compiler?)\n"; }
getch();
return 0;
}
Output(When executed on Visual studio 2008):
caught other exception (non-compliant compiler?)
But, I was expecting the output to be:
unexpected called
caught int
NOTE: I executed this program on Visual Studio 2008.
Yes, as per the Standard the output should be[#1]:
unexpected called
caught int
gcc gives accurate result.
Note that, MSVC is notoriously buggy w.r.t handling exception specifications. Exception specifications are considered a failed experiment.
AFAIK, MSVC does not implement exception specifications, except for the empty ones (throw()/nothrow)
C++03 Standard:
[#1] 15.5.2 The unexpected() function [except.unexpected]
The unexpected() function shall not return, but it can throw (or re-throw) an exception. If it throws a new exception which is allowed by the exception specification which previously was violated, then the search for another handler will continue at the call of the function whose exception specification was violated....