I have the below example. (My actual project is a multi-threaded one and I have the terminate handler set for all of them.) I have a couple of questions here.
My terminate handler doesn't do anything fancy. It just says that an error occured and exits. I read that it i good practice to add the handler. Why is that so and do I really need in this case ?
If I don't have the handler, I get the type of exception thrown. terminate called after throwing an instance of 'char const*' But when I use the handler, I am unable to get it. Even if I use current_exception, I am unable to get the type of exception. (Here its obviously char* but in my case it could be anything so I can't catch correctly. Even if I use catch{...}, the message and type are lost). Is there anyway to get the message. If not message, atleast can I get type of the exception thrown ?
// set_terminate example
#include <iostream>
#include <exception>
#include <cstdlib>
using namespace std;
void myterminate () {
cerr << "terminate handler called\n";
abort(); // forces abnormal termination
}
int main (void) {
//set_terminate (myterminate);
throw "TEST"; // unhandled exception: calls terminate handler
return 0;
If you can live with the portability restriction implied by <cxxabi.h>1,
then you might be OK with the backstop() terminate-handler below:
main.cpp
#include <iostream>
#include <exception>
#include <stdexcept>
#include <cstdlib>
#include <cxxabi.h>
void backstop()
{
auto const ep = std::current_exception();
if (ep) {
try {
int status;
auto const etype = abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &status);
std::cerr << "Terminating with uncaught exception of type `" << etype << "`";
std::rethrow_exception(ep);
} catch(const std::exception& e) {
std::cerr << " with `what()` = \"" << e.what() << "\"";
} catch(...) {}
std::cerr << std::endl;
}
std::abort();
}
int main(int argc, char *argv[])
{
std::set_terminate(backstop);
if (argc > 1) {
throw argv[1];
} else {
throw std::runtime_error("I am too tired to carry on");
}
return 0;
}
This will always report the type of the uncaught exception, and if that type derives from
std::exception, it will also report the what() of that exception. E.g.
$ g++ --version
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
...
$ g++ -Wall -Wextra -pedantic main.cpp; ./a.out Whoops!
Terminating with uncaught exception of type `char*`
Aborted (core dumped)
$ clang++ --version
clang version 10.0.0-4ubuntu1
...
$ clang++ -Wall -Wextra -pedantic main.cpp; ./a.out
Terminating with uncaught exception of type `std::runtime_error` with `what()` = "I am too tired to carry on"
Aborted (core dumped)
Note that you might avoid calling set_terminate(backstop) - which conceivably might be
countermanded someplace else in a big complicated program - and ensure that any
exception escaping the body of main is caught in a function try-block, i.e.
replace main with:
int main(int argc, char *argv[]) try
{
if (argc > 1) {
throw argv[1];
} else {
throw std::runtime_error("I am too tired to carry on");
}
return 0;
}
catch(...) {
backstop();
}
This program will behave just as before.
[1] You'll have at least g++, clang++, icc; you won't have MS C++
As your metioned, If you want to let your terminate do something fancy, you could write a terminate handler function and call it as a parameter of std::set_terminate.And I think it might be useful to add a backtrace in this function to give more information.Although the name of functions is mangled by the compiler, but still you could see where this error occurred.
And if you want to show the exception, you can add a try-catch block in terminate-handler function.
By the way, I think it may be necessary to using signal function to deal with segmental default error, by doing this your program is more complete in exception handle.
In utils.h file :
#include <stdexcept>
#include <execinfo.h>
#include <exception>
#include <stdexcept>
#include <cstdlib>
#include <csignal>
// This function is used for handle segmental fault
inline void segfaultHandler(int signal __attribute__((unused)))
{
void *stackArray[20];
size_t size = backtrace(stackArray, 10);
std::cerr << "Segmentation fault! backtrace: ";
char** backtrace = backtrace_symbols(stackArray, size);
for (size_t i = 0; i < size; i++)
{
std::cerr << "\t" << backtrace[i]
}
abort();
}
// This is terminate handle function
inline void exceptionHandler()
{
static bool triedThrow = false;
try
{
if(!triedThrow)
{
triedThrow = true;
throw;
}
}
catch( const std::exception &e)
{
std::cerr << "Caught unhandled exception: " << e.what();
}
catch(...){}
void *stackArray[20];
size_t size = backtrace(stackArray, 10);
std::cerr << "Segmentation fault! backtrace: ";
char** backtrace = backtrace_symbols(stackArray, size);
for (size_t i = 0; i < size; i++)
{
std::cerr << "\t" << backtrace[i]
}
abort();
}
And in main, Using Mike Kinghan's code for example
#include <iostream>
#include "utils.h"
int main(int argc, char *argv[])
{
signal(SIGSEGV, segfaultHandler);
std::set_terminate(exceptionHandler);
if (argc > 1) {
throw argv[1];
} else {
throw std::runtime_error("I am too tired to carry on");
}
return 0;
}
Related
I was reading the following post:
What changes introduced in C++14 can potentially break a program written in C++11?
and also the isocpp page:
https://isocpp.org/files/papers/p0636r0.html
So I became curious, according to the Standard: What changes introduced in C++11 can potentially break a program written in C++98?
Big one that stands out -- throwing exceptions from destructors.
In C++98 you can have programs that do this and work fine if you are careful.
In C++11 you will often have to explicitly declare the dtor noexcept(false).
Nice blog post here, on Andrzej's C++ blog.
In short, the following program used to run successfully in C++03 (under some definition of “success”):
struct S
{
~S() { throw runtime_error(""); } // bad, but acceptable
};
int main()
{
try { S s; }
catch (...) {
cerr << "exception occurred";
}
cout << "success";
}
In C++11, the same program will trigger the call to std::terminate.
Here is another case related to destructors are noexcept(true) in C++11:
// A simple program that demonstrates how C++11 and pthread_cancel don't play
// nicely together.
//
// If you build without C++11 support (g++ threadkill.cpp -lpthread), the
// application will work as expected. After 5 seconds, main() will cancel the
// thread it created and the program will successfully exit.
//
// If you build with C++11 support(g++ -std=c++11 threadkill.cpp -lpthread),
// the program will crash because the abi::__forced_unwind exception will
// escape the destructor, which is implicitly marked as noexcept(true) in
// C++11. If you mark the destructor as noexcept(false), the program does
// not crash.
#include <iostream>
#include <unistd.h>
#include <string.h>
class sleepyDestructorObject
{
public:
~sleepyDestructorObject() //noexcept(false)
{
std::cout << "sleepy destructor invoked" << std::endl;
while(true)
{
std::cout << "." << std::flush;
sleep(1);
}
}
};
void* threadFunc( void* lpParam )
{
sleepyDestructorObject sleepy;
return NULL;
}
int main(int argc, char** argv)
{
pthread_t tThreadID;
pthread_create(&tThreadID, NULL, threadFunc, NULL);
sleep(5);
pthread_cancel(tThreadID);
pthread_join(tThreadID, NULL);
return 0;
}
Original reference:
https://gcc.gnu.org/ml/gcc-help/2015-08/msg00036.html
Given a file that contains one integer per line, I am trying to use this code to read the file and store the numbers in a vector.
Strangely, after finishing reading the file, my program is printing the string "stoi". Is this just a behavior of std::stoi? I couldn't find anything about this in documentation.
I am using g++ 6.2.1.
Here is the relevant code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
void usage() {
std::cout << "Usage: ./binary_tree [FILE]\n";
}
int main(int argc, char* argv[]) {
try{
if (argc <= 1) {
usage();
return 1;
}
std::ifstream inputFile;
inputFile.open(argv[1], std::ios::in);
if (!inputFile.is_open()) throw std::runtime_error("Failed to open file");
std::string line;
std::vector<int> nums;
while(!inputFile.eof()) {
getline(inputFile, line);
int num = std::stoi(line);
nums.push_back(num);
}
// Clean up
inputFile.close();
return 0;
}
catch(const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
I am trying to implement lock free queue of user defined data type using boost library, but I am getting wrong result.
Please help me out where I am doing wrong.
#include <boost/lockfree/spsc_queue.hpp>
#include <thread>
#include <iostream>
#include <string.h>
#include <time.h>
class Queue
{
private:
unsigned char *m_data;
int m_len;
public:
Queue(unsigned char *data,int len);
Queue(const Queue &obj);
~Queue();
Queue & operator =(const Queue &obj);
unsigned char *getdata()
{
return m_data;
}
int getint()
{
return m_len;
}
};
Queue::Queue(unsigned char* data, int len)
{
m_len=len;
m_data=new unsigned char[m_len];
memcpy(m_data,data,m_len);
}
Queue::Queue(const Queue& obj)
{
m_len= obj.m_len;
m_data=new unsigned char[m_len];
memcpy(m_data,(unsigned char *)obj.m_data,m_len);
}
Queue::~Queue()
{
delete[] m_data;
m_len=0;
}
Queue & Queue::operator =(const Queue &obj)
{
if(this != &obj)
{
m_len=obj.m_len;
m_data=new unsigned char[m_len];
memcpy(m_data,(unsigned char *)obj.m_data,m_len);
}
return *this;
}
boost::lockfree::spsc_queue<Queue*> q(10);
void produce()
{
int i=0;
unsigned char* data=(unsigned char *)malloc(10);
memset(data,1,9);
Queue obj(data,10);
Queue *pqueue=&obj;
printf("%d\n",pqueue->getint());
q.push(pqueue);
}
void consume()
{
Queue *obj;
q.pop(&obj);
printf("%d\n",obj->getint());
}
int main(int argc, char** argv) {
// std::thread t1{produce};
// std::thread t2{consume};
//
// t1.join();
// t2.join();
produce();
consume();
return 0;
}
As per boost::lockfree::queue requirements I created following in class.
Copy Constructor
Assignment Operator
Destructor
Please let me know if anything other requires.
Thanks.
You're using malloc in C++.
You die.
You have 2 lives left.
Seriously, don't do that. Especially since using it with delete[] is clear cut Undefined Behaviour.
Sadly you lose another life here:
Queue obj(data,10);
Queue *pqueue=&obj;
q.push(pqueue);
You store a pointer to a local. More Undefined Behaviour
You have 1 life left.
Last life at
q.pop(&obj);
You pop using an iterator. It will be treated as an output iterator.
You get a return that indicates the number of elements popped, and items
will be written to &obj[0], &obj[1], &obj[2], etc.
Guess what? Undefined Behaviour.
See also: Boost spsc queue segfault
You died.
You're already dead. But you forsake your afterlife with
printf("%d\n",obj->getint());
Since pop might not have popped anything (the queue may have been empty), this in itself is Undefined Behaviour.
The funny part is, you talk about all these constructor requirements but you store pointers in the lockfree queue...?! Just write it:
typedef std::vector<unsigned char> Data;
class Queue {
private:
Data m_data;
public:
Queue(Data data) : m_data(std::move(data)) {}
Queue() : m_data() {}
unsigned char const *getdata() const { return m_data.data(); }
size_t getint() const { return m_data.size(); }
};
boost::lockfree::spsc_queue<Queue> q(10);
Live On Coliru
Notes:
you need to make the consumer check the return code of pop. The push might not have happened, and lock free queues don't block.
you don't need that contraption. Just pass vectors all the way:
C++ Code
Live On Coliru
#include <boost/lockfree/spsc_queue.hpp>
#include <thread>
#include <iostream>
#include <vector>
typedef std::vector<unsigned char> Queue;
boost::lockfree::spsc_queue<Queue> q(10);
void produce() {
Queue obj(10, 1);
std::cout << __FUNCTION__ << " - " << obj.size() << "\n";
q.push(std::move(obj));
}
void consume() {
Queue obj;
while (!q.pop(obj)) { }
std::cout << __FUNCTION__ << " - " << obj.size() << "\n";
}
int main() {
std::thread t1 {produce};
std::thread t2 {consume};
t1.join();
t2.join();
}
I am trying to parse a list input from the command line.
My class is derived from vector
The compiler complains about a overloaded validate being ambiguous.
I can see why, but do not know how to solve this issue.
Please help.
Below is a minimal example that generates the error. If the type of ch_list is changed to a vector, this minimal example compiles.
// g++ -std=c++11 -Wall -Wextra -pedantic test.cpp -o test -lboost_program_options -lboost_system
#include <vector>
#include <boost/program_options.hpp>
#include <iostream>
#include <vector>
using namespace std;
class mylist : public vector<int> {
public:
friend istream &operator>>(istream &is, mylist& l) {
int val;
is >> val;
l.push_back(val);
return is;
}
friend ostream& operator<<(ostream& os, const mylist& l) {
return os << l[0];
}
};
int main (int argc, char* argv[])
{
//vector<int> ch_list; // This works
mylist ch_list; // This doesn't
namespace po = boost::program_options;
po::options_description desc("Allowed options");
desc.add_options()
("ch", po::value<decltype(ch_list)>(&ch_list), "Set channel numbers")
;
po::variables_map vm;
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
}
catch (po::error& e) {
cerr << "ERROR: " << e.what() << "\n";
return EXIT_FAILURE;
}
if (!ch_list.empty())
cout << ch_list[0] << "\n";
return EXIT_SUCCESS;
}
I get these errors
/usr/include/boost/program_options/detail/value_semantic.hpp: In instantiation of ‘void boost::program_options::typed_value<T, charT>::xparse(boost::any&, const std::vector<std::basic_string<charT> >&) const [with T = mylist; charT = char]’:
test.cpp:47:5: required from here
/usr/include/boost/program_options/detail/value_semantic.hpp:169:13: error: call of overloaded ‘validate(boost::any&, const std::vector<std::basic_string<char> >&, mylist*, int)’ is ambiguous
/usr/include/boost/program_options/detail/value_semantic.hpp:169:13: note: candidates are:
/usr/include/boost/program_options/detail/value_semantic.hpp:81:10: note: void boost::program_options::validate(boost::any&, const std::vector<std::basic_string<charT> >&, T*, long int) [with T = mylist; charT = char]
/usr/include/boost/program_options/detail/value_semantic.hpp:129:10: note: void boost::program_options::validate(boost::any&, const std::vector<std::basic_string<charT> >&, std::vector<_RealType>*, int) [with T = int; charT = char]
You can use custom validator. Your code would be:
#include <vector>
#include <boost/program_options.hpp>
#include <iostream>
#include <vector>
using namespace std;
namespace po = boost::program_options;
class mylist : public vector<int> {
public:
};
void validate(boost::any& v,
const vector<string>& values,
mylist*, int) {
mylist dvalues;
for(vector<string>::const_iterator it = values.begin();
it != values.end();
++it) {
stringstream ss(*it);
copy(istream_iterator<int>(ss), istream_iterator<int>(),
back_inserter(dvalues));
if(!ss.eof()) {
throw ("Invalid coordinate specification");
}
}
v = mylist(dvalues);
}
int main (int argc, char* argv[])
{
//vector<int> ch_list; // This works
mylist ch_list; // This doesn't
po::options_description desc("Allowed options");
desc.add_options()
("ch", po::value< mylist >(&ch_list)->multitoken(), "Set channel numbers")
;
po::variables_map vm;
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
}
catch (po::error& e) {
cerr << "ERROR: " << e.what() << "\n";
return EXIT_FAILURE;
}
for (auto cc : ch_list)
cout << cc << endl;
return EXIT_SUCCESS;
}
Reference: boost::program_options config file option with multiple tokens
What the behavior of a deadline_timer whose expiration is 0 milliseconds?
In my code, I have:
boost::asio::io_service ios;
...
boost::asio::deadline_timer ptimer(ios);
ptimer.expires_from_now(boost::posix_time::milliseconds(duration)); // Duration might be 0 sometimes
boost::system::error_code ec;
ptimer.async_wait(boost::bind(&SomeTimeOutHandler, this, ec));
I found that if duration == 0, the handler SomeTimeOutHandler never gets called.
I want it gets called.
However, if I change to duration == 1, the handler does get called.
So what the exact behavior it should be when the deadline_timer's expiration is 0?
Edit:
But the following HelloWorld test program is working (suggested by #Roger):
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
void SomeTimeOutHandler(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << "SomeTimeOutHandler error_code" << std::endl;
}
else
{
std::cout << "I'm in good shape" << std::endl;
}
}
void Test(int duration)
{
boost::asio::io_service ios;
boost::asio::deadline_timer ptimer(ios);
ptimer.expires_from_now(boost::posix_time::milliseconds(duration));
boost::system::error_code ec;
ptimer.async_wait(boost::bind(&SomeTimeOutHandler, ec));
ios.run();
// boost::this_thread::sleep(boost::posix_time::milliseconds(duration * 2 + 1000));
}
int main(int argc, char* argv[])
{
Test(10); // Test(0);
return 0;
}