I'm compiling the following against eigen 3.3.5:
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <unsupported/Eigen/KroneckerProduct>
template <typename eT, int SIDE>
inline
auto
xLeft(const Eigen::Matrix<eT, SIDE, SIDE> & M)
{
Eigen::SparseMatrix<double> Id(SIDE, SIDE);
Id.setIdentity();
return kroneckerProduct(M.transpose(), Id);
}
void fail()
{
Eigen::Matrix<double,2,2> M = Eigen::Matrix<double,2,2>::Random();
std::cout << "die:" << xLeft(M) << "\n";
}
int main() { fail(); return 0; }
and getting a crash, anyone else see this, is this an Eigen bug or am I doing something wrong that I just can't see?
also:
g++ (GCC) 7.3.1 20180712 (Red Hat 7.3.1-6)
Related
I have BOOST installed on my Windows PC with Mingw. The BOOST installation basically works, but when I use a macro I got following error message:
macro "BOOST_PP_NOT_EQUAL_1" defined here
Under Linux it works!
Anybody out there what can help me?
Or at least give some hint.
Here are my marco's:
#include <iostream>
#include <ostream>
#include <set>
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
class EnumShowValue {
private:
static bool showValueFlag;
public:
explicit EnumShowValue(const bool flag) { EnumShowValue::showValueFlag = flag; }
static bool showValue() { return EnumShowValue::showValueFlag; }
};
inline std::ostream &operator <<(std::ostream &os, const EnumShowValue &) { return os; }
// Defines a entry of the enumerations either with an initialization value or with a default value.
#define ENUM_FIELD(C, T, ARGS)\
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE(ARGS), 2),\
BOOST_PP_TUPLE_ELEM(0, ARGS) = BOOST_PP_TUPLE_ELEM(1, ARGS),\
BOOST_PP_TUPLE_ELEM(0, ARGS)),
// Define output of a single enumeration value.
#define ENUM_OUTPUT_CASE(C, T, ARGS)\
case T::BOOST_PP_TUPLE_ELEM(0, ARGS):\
os << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(0, ARGS));\
break;
#define ENUM_INSERT(C, T, ARGS)\
this->insert(T::BOOST_PP_TUPLE_ELEM(0, ARGS));
#define ENUM_DEFINE_SET(C, T, ARGS)\
class Collection : public std::set<C> {\
public:\
Collection() : std::set<C>() {\
BOOST_PP_SEQ_FOR_EACH(ENUM_INSERT, C, ARGS)\
}\
};\
Collection collection;
// Works only if the enumeration values are unique.
#define ENUM(C, T, ARGS) \
enum class C : T {\
BOOST_PP_SEQ_FOR_EACH(ENUM_FIELD, C, ARGS)\
};\
ENUM_DEFINE_SET(C, T, ARGS)\
std::ostream &operator <<(std::ostream &os, const C val);\
std::ostream &operator <<(std::ostream &os, const C val) {\
switch (val) {\
BOOST_PP_SEQ_FOR_EACH(ENUM_OUTPUT_CASE, C, ARGS)\
default:\
os << "illegal value: " << BOOST_PP_STRINGIZE(C);\
if (!EnumShowValue::showValue()) {\
os << '(';\
if (sizeof(T) == 1) {\
os << static_cast<int>(val);\
} else {\
os << static_cast<T>(val);\
}\
os << ')';\
}\
}\
if (EnumShowValue::showValue()) {\
os << '(';\
if (sizeof(T) == 1) {\
os << static_cast<int>(val);\
} else {\
os << static_cast<T>(val);\
}\
os << ')';\
}\
return os;\
}
and a example how to use:
(it defines some logging levels)
namespace logging {
ENUM(Level, unsigned char, ((DEBUG)(INFO)(WARNING)(ERR)))
}
If found a solution show below.
What I was not able so solve is a more general solution in with I can define the name of the enumeration, the basic type and the values in a #define or in an template.
Has anybody an idea how to do this?
#include <cstdint>
#include <iostream>
#include <ostream>
#define Days\
X(Monday, = 100)\
X(Tuesday,)\
X(Wednesday,)\
X(Thursday,)\
X(Friday,)\
X(Saturday, = 110)\
X(Sunday,)
enum class Weekdays : uint8_t {
#define X(a, b) a b,
Days
#undef X
};
std::ostream &operator <<(std::ostream &os, const Weekdays e);
std::ostream &operator <<(std::ostream &os, const Weekdays e) {
switch (e) {
#define X(a, b) case Weekdays::a: os << #a; break;
Days;
#undef X
default:
os << "invalid value: Weekdays=" << uint64_t(e);
}
return os;
}
int main(const int /*argc*/, const char *const /*argv*/[]) {
std::cout << Weekdays::Monday << std::endl;
std::cout << Weekdays::Tuesday << std::endl;
std::cout << Weekdays::Saturday << std::endl;
std::cout << Weekdays(99) << std::endl;
return EXIT_SUCCESS;
}
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;
}
My gcc version is 4.8.5
posix gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
I have two cpp files:
1.cpp and 2.cpp
while there is a static function in 1.cpp called by 2.cpp。
In most machine,we should like this:
g++ 2.cpp 1.cpp
or it will cause compile error or runtime error。
However,in my machine with gcc 4.8.5,I must compile using “g++ 1.cpp 2.cpp” to make it run successful。
Is this the property of gcc4.8.5? or there is something wrong on my soft,or I used it wrong?
==============================================================
My machine is centos7 installed on virtulbox of mac. Here is my code:
1.h
#include <map>
using namespace std;
class A {
private:
A();
static A _instance;
map<int, int> test_map;
public:
static A& get_instance();
static void fun();
};
1.cpp
#include <iostream>
#include "1.h"
using namespace std;
A A::_instance;
A::A() {
cout << "A::A()\n";
}
A& A::get_instance() {
cout << "A::get_instance()\n";
return A::_instance;
// static A instance;
// return instance;
}
void A::fun() {
cout << "A::fun()\n";
get_instance().test_map[1];
}
main.cpp
#include <iostream>
#include "1.h"
using namespace std;
int test() {
cout << "test()\n";
A::fun();
return 0;
}
int y = test();
int main() {
cout << "main()\n";
A::fun();
}
In most machine and in what I see in the web, we should compile like this:
g++ main.cpp 1.cpp
But in my machine, I must compile like this:
g++ 1.cpp main.cpp
what's wrong with my machine or my gcc?
I think you are facing the static initialization order fiasco which is a classical C++ bug. If initialization function test() in main.cpp is called before constructor for A::_instance has been called, your code will access uninitialized A::_instance::test_map field which is likely to cause segmentation fault. I suggest you rewrite getInstance to create instance when needed:
A *A::_instance;
A& A::get_instance() {
cout << "A::get_instance()\n";
if(!_instance)
_instance = new A;
return *A::_instance;
}
As a side note, I suggest you to use AddressSanitizer to autodetect this and similar types of errors.
The following sample code works fine under linux using g++4.8.2, using boost1_56. However, I get a strange linker error under MacOS X (Yosemite) using clang:
ld: internal error: atom not found in symbolIndex(__ZNSt3__112__hash_tableINS_17__hash_value_typeIKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN15FRUIT_TUPLES4dataEEENS_22__unordered_map_hasherIS8_SB_NS9_8key_hashELb1EEENS_21__unordered_map_equalIS8_SB_NS9_9key_equalELb1EEENS5_ISB_EEE15__insert_uniqueIRKNS_4pairIS8_SA_EEEENSL_INS_15__hash_iteratorIPNS_11__hash_nodeISB_PvEEEEbEEOT_) for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Proces
The main.cpp file
#include "TupleFruits.hpp"
int main()
{
map_t fruitHash = InitializeFruitHash();
std::string fruit = "BANANA";
auto itr = fruitHash(fruit);
if (fruitHash.end() == itr)
{
std::cout << fruit << " not found in hash" << std::endl;
exit(1);
}
}
The FruitHash.cpp file:
#include "TupleFruits.hpp"
map_t InitializeFruitHash()
{
static map_t m;
data dBANANA = {0, 0, 6, false};
data dGRAPEFRUIT = {1, 1, 6, false};
data dSTRAWBERRY = {2, 2, 6, false};
m[BANANA] = dBANANA;
m[GRAPEFRUIT] = dGRAPEFRUIT;
m[STRAWBERRY] = dSTRAWBERRY;
return m;
}
The include file "HashData.hpp
#ifndef HASH_DATA_HPP
#define HASH_DATA_HPP
#include <string>
#include <unordered_map>
#include <cstring>
#include <iostream>
#include <tuple>
#include <boost/functional/hash.hpp>
typedef std::string fruit_key_t;
namespace HASH_TUPLES
{
struct key_hash : public std::unary_function<fruit_key_t, std::size_t>
{
std::size_t operator()(const fruit_key_t& k) const
{
std::hash<std::string> hash_fn;
return hash_fn(k);
}
};
struct key_equal : public std::binary_function<fruit_key_t, fruit_key_t, bool>
{
bool operator()(const fruit_key_t& v0, const fruit_key_t& v1) const
{
return (v0 == v1);
}
};
struct data
{
int row;
int column;
int precision;
bool isRipe;
inline bool operator ==(data d)
{
if (d.row == row && d.column == column)
return true;
else
return false;
}
friend std::ostream& operator << (std::ostream& os, const data& rhs) //Overloaded operator for '<<'
{ //for struct output
os << rhs.row << ", "
<< rhs.column;
return os;
}
};
typedef std::unordered_map<const fruit_key_t, data, key_hash, key_equal> map_t;
// ^ this is our custom hash
}
template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type,
typename T::mapped_type,
bool>
{
public:
bool operator() (typename T::value_type &pair,
typename T::mapped_type i) const
{
return pair.second == i;
}
};
#endif
The include file "TupleFruits.hpp"
#ifndef TUPLESFRUITS_HPP
#define TUPLESFRUITS_HPP
#include <boost/interprocess/containers/string.hpp>
#include "HashData.hpp"
using namespace HASH_TUPLES;
map_t InitializeFruitHash();
static std::string BANANA = "banana";
static std::string GRAPEFRUIT = "grapefruit";
static std::string STRAWBERRY = "strawberry";
#endif
I figured it out. Somehow -s (strip all symbols from binary) snuck in my Makefile
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