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?
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 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.
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
I need to be able to use a single fstream to have platform-independent way of using files. In particular, I need to be able to support file paths with unicode characters on Windows with as minimal intrusion into code to support it as possible. As such, it seemed like boost iostreams could provide the answer. However, upon trying to use it, I get two failures which cause me concern. See the following sample code:
// MinGW (MSYS)
// GCC 4.7.2
// Boost 1.50.0
// g++ -g ifstreamtest.cpp -o test.exe -I /t/tools/boost/boost_1_50_0 -L /t/tools/boost/boost_1_50_0/stage/lib -lboost_system-mgw47-mt-d-1_50 -lboost_filesystem-mgw47-mt-d-1_50 -lboost_locale-mgw47-mt-d-1_50 -lboost_iostreams-mgw47-mt-d-1_50
#include <boost/locale.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/filesystem/path.hpp>
namespace MyNamespace
{
typedef ::boost::iostreams::file_descriptor fd;
typedef ::boost::iostreams::stream< ::boost::iostreams::file_descriptor> fstream;
typedef ::boost::iostreams::stream< ::boost::iostreams::file_descriptor_sink> ofstream;
typedef ::boost::iostreams::stream< ::boost::iostreams::file_descriptor_source> ifstream;
} // namespace MyNamespace
int main(int argc, char **argv)
{
// Imbue boost filesystem codepoint conversions with local system
// Do this to ensure proper UTF conversion.
boost::filesystem::path::imbue(boost::locale::generator().generate(""));
// Test file path.
boost::filesystem::path file_path("test.txt");
// Anonymous scope for temporary object.
{
// Open file in ctor, write to output, neglect to clean up until dtor.
MyNamespace::ofstream output(file_path, std::ios_base::out | std::ios_base::app);
if ( output.is_open() == false ) std::cout << "Unable to open #" << __LINE__ << std::endl;
output << "test line 1" << std::endl;
std::cout << "done #" << __LINE__ << std::endl;
}
// Temporary object destroyed while still open.
// Anonymous scope for temporary object.
{
// Open file in ctor, write to output, specifically close file.
MyNamespace::ofstream output1(file_path, std::ios_base::out | std::ios_base::app);
if ( output1.is_open() == false ) std::cout << "Unable to open #" << __LINE__ << std::endl;
output1 << "test line 2" << std::endl;
output1.close();
std::cout << "done #" << __LINE__ << std::endl;
}
// Temporary object destroyed.
// Anonymous scope for temporary object.
{
// Default-ctor; open later. Write to file, neglect to clean up until dtor.
MyNamespace::ofstream output2;
// Next line causes "Assertion failed: initialized_, file t:/tools/boost/boost_1_50_0/boost/iostreams/detail/optional.hpp, line 55"
output2->open(file_path, std::ios_base::out | std::ios_base::app);
if ( output2.is_open() == false ) std::cout << "Unable to open #" << __LINE__ << std::endl;
output2 << "blah test test blah" << std::endl;
}
// Temporary object destroyed.
// MyNamespace::ifstream input;
// Compile success, but linker failure:
// s:\reactor\utf8stream/ifstreamtest.cpp:42: undefined reference to `void boost::iostreams::file_descriptor_source::open<boost::filesystem::path>(boost::filesystem::path const&, std::_Ios_Openmode)'
// input->open(file_path, std::ios_base::in);
std::cout << "done." << std::endl;
return 0;
}
On Windows, I am limited to GCC 4.7.2 and Boost 1.50.
The comments explain the two failures, but I will expand on them here. The first and most problematic to me is when I try to use the stream object as a "normal" fstream object. If I open the fstream in its constructor, then all is fine and dandy (as can be seen in the first two anonymous scopes). But if I allocate the fstream object and then attempt to open it later, "Bad Things" happen.
If I try to invoke boost::iostreams::stream::open(), I get compiler errors saying that it can't convert parameter 1 (boost::filesystem::path) to a boost::iostreams::file_descriptor_sink. Why should that not work when it can be constructed with a boost::filesystem::path? In either case, attempting to call boost::iostreams::file_descriptor_sink::open() by using the stream's operator->() fails an assertion (as shown in the third anonymous scope). This is quite evil as it would seem to me that it should throw an exception instead of failing an assertion. Failing an assertion would indicate to me that there's a bug in the boost code.
The second failure I have is that the typedefed fstream and ofstream seem to work (well, compile and link) just fine. But when I try to use the ifstream, I get a linker failure when trying to call ifstream->open(); I get this on Windows (MinGW configuration as stated before) as well as on OS X 10.8.5 with Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn). Since it compiles fine and the only difference between the two there is whether it's a source or a sink... and both should be able to open a file... it makes me think that this is also a bug in boost.
Any thoughts or suggestions?
Regarding the compiler error:
I can reproduce the linking error on Linux, with g++ and Clang++, so it's not a specific Windows problem (I'm also using Boost 1.55.0, so it's not specific to 1.50).
I suppose it is caused by a template definition that is allowed in the header file, but not implemented in the source/library.
Solution (for the linking problem only): Instead of
input->open(file_path, std::ios_base::in);
use
input->open(file_path.string(), std::ios_base::in);
This circumvents the potentially misdefined template by using a string-based constructor.
Regarding the assertion error:
The issue is you need to initialize the file_descriptor_sink separately, else the iostream initialization won't be handled properly. Use this code:
//We need to initialize the sink separately
boost::iostreams::file_descriptor_sink output2Sink(file_path, std::ios_base::out | std::ios_base::app);
MyNamespace::ofstream output2(output2Sink);
if ( output2.is_open() == false ) std::cout << "Unable to open #" << __LINE__ << std::endl;
output2 << "blah test test blah" << std::endl;
open() doesn't seem to reset the optional that causes the assertion.
The same method needs to be applied to the the MyNamespace::ifstream:
boost::iostreams::file_descriptor_source inputSource(file_path, std::ios_base::in);
MyNamespace::ifstream input(inputSource);
//Test reading back what we wrote earlier
std::string inputContent;
input >> inputContent;
//Prints: blah (only the first word is read!)
std::cout << "Read from test.txt: " << inputContent << std::endl;
Also note that it is not neccessary to apply the solution to avoid the compiler error from above.
With these modifications your program appears to be working on my system.
I keep getting this error message and don't know why.
dyld: Library not loaded: libboost_thread.dylib
Referenced from: /Users/adhg/Documents/workspace_cpp/Boost_101/Release/Boost_101
Reason: image not found
the code:
#include <iostream>
#include <boost/thread.hpp>
void workerFunction() {
boost::posix_time::seconds workTime(3);
std::cout << "Worker: running" << std::endl;
boost::this_thread::sleep(workTime);
std::cout << "Worker: finished" << std::endl;
}
int main() {
std::cout << "main: startup" << std::endl;
boost::thread workerThread(workerFunction);
std::cout << "main: waiting for thread" << std::endl;
workerThread.join();
std::cout << "main: done" << std::endl;
return 0;
}
What I did is simply follow the instructions here and in many other places, the basics:
download boost
unzip to folder
./bootstrap.sh
./bjam
you will note that the usr/local/boost... is where I actually placed my folder (it exists) and under usr/local/boost_1_54_0/stage/lib I have the libboost_thread and so forth. Still...not sure why I get this error.
My settings looks like this now:
Can anyone point out what am I doing wrong?
This looks to be a dynamic linking issue, and from a little research, it seems that this can be solved by setting the DYLD_LIBRARY_PATH environment variable to point to where the libraries are located (in your case, /usr/local/boost_1_54_0/stage/lib). You may wish to read this similar question and also this external page, the latter of which states
This happend because I built boost from source and kept it local. Thus the path to the library was not the default one. To solve this problem we have to edit the environment variable DYLD_LIBRARY_PATH, which is analogous to linux LD_LIBRARY_PATH
(Also, I'll just mention that if you are only interested in threading capabilities and not Boost as a whole, you could use C++11's <thread> header.)