How to get an explanatory string from std::regex_error? - c++

My program is throwing an std::regex_error(). I'd like to know what the error is, since the regex looks legit to me. I did essentially this:
try {
// offending code
} catch (std::regex_error& e) {
log_error("Regex error: " << e.what() << ", " << e.code());
}
The output is:
Regex error: regex_error, 4
This isn't particularly helpful. What does 4 mean? The en.cppreference.com entry for code() only says:
Returns the std::regex_constants::error_type that was passed to the std::regex_error constructor.
The entry for error_type gives a list of error codes, all of whose exact values are "unspecified".
Do I have no recourse but to do something like this?
switch (e.code()) {
case std::regex_constants::error_collate: return "error_collate";
case std::regex_constants::error_ctype: return "error_ctype";
// etc ...
}

This is a quality-of-implementation issue in the standard C++ library, which is a nice way of saying that it's a bug. GCC bug 67361, to be exact ("std::regex_error::what() should say something about the error_code").
There is a recently submitted patch in the bug report, so I suppose that it will eventually show up as an upgrade. [Update: According to the bug report above, it was fixed in v6.1 (released April 26, 2016) but the bug report was not marked as resolved until November 19, 2018. Anyway, if you have a reasonably recent distribution, this should not be a problem any more.]
In the meantime, you have little option but to roll your own code->message conversion function. (Or, as an interim debugging method, consult include/bits/regex_error.h)

An alternative to using the switch is to define your own enum for each regex error code and cast the result to that, giving you better runtime debugging aid.
enum class RegexError {
collate = std::regex_constants::error_collate,
ctype = std::regex_constants::error_ctype,
// etc
};
RegexError errorCode = static_cast<RegexError>( e.code() );
// your debugger will now show you what the meaning of errorCode is
That way you don't need to use strings.
However, if you want to display the error to the user in a human-readable fashion then you will need to use strings, but you can use a map to store them:
map<RegexError, wchar_t const * const> errorMessages;
errorMessages[RegexError::collate] = L"the expression contains an invalid collating element name";
errorMessages[RegexError::ctype ] = L"the expression contains an invalid character class name";
// etc

Related

Function abi::__cxa_current_exception_type() returns non-ASCII characters

I'm running into an issue where running on a remote machine (but not locally) results in an unexpected exception of unknown type. I attempted to get more diagnostic information by wrapping things with a try {} catch {} with a range of possible exception types (including std::exception const &) but the exception still falls through to the catch(...) clause.
For lack of a better option, I attempted to get the type of the exception with (the GCC/Clang specific function) abi::__cxa_current_exception_type()->name() (within the catch(...) block), but this results in an output with non-ASCII characters. (Specifically, I'm getting 0��m- printed.) Attempting to pass it through abi::__cxa_demangle() before printing doesn't seem to help:
try {
// code which throws the exception
} catch (std::exception const & e) {
std::cout << "std::exception: " << e.what() << '\n';
} catch (...) {
int status = 0;
std::cout << "__cxa_current_exception_type() reports error type as: " << abi::__cxa_demangle( abi::__cxa_current_exception_type()->name(),0,0,&status) << '\n';
}
I'm a little surprised that the mangled name contains non-ASCII characters. (And to be explicit, we don't use non-ASCII identifiers in our code, and I'm not aware of any of our dependencies doing so.) I've also attempted to read through some name mangling resources to figure out what might be going on with the 0��m-, but I didn't find any likely reasons for the leading 0, or why there might be non-ASCII characters in the mangled name.
Do people have any ideas as to what might be going on here, and what sort of exception type is being thrown here? Or alternatively, are there approaches I may have missed to figure out the type?

How to not have any error when try to get a not existing node

Could somebody knows what kind of exception return the following code inside the "try" ?
I try to use the 3 kind of "catch (exception)" and no one seems to work.
try
{
std::cout << "try to get not existing path" << std::endl;
std::string path = this->m_Tree.get<std::string>(PATH);
}
catch (const boost::property_tree::ptree_bad_path& e)
{
std::cout << "ptree_bad_path" << std::endl;
}
Thank you for your help.
Look at the docs:
Three Ways of Getting Data
There are three versions of get: get, get (default-value version), and get_optional, which differ by failure handling strategy. All versions take path specifier, which determines in which key to search for a value. It can be a single key, or a path to key, where path elements are separated with a special character (a '.' if not specified differently). For example debug.logging.errorlevel might be a valid path with dot as a separator.
So, just use get_optional<std::string> I'd say
ptree pt;
/* ... */
boost::optional<float> v = pt.get_optional<float>("a.path.to.float.value");

Compare boost::system::error_category

The following comparison fails for an error whom outputs "asio.misc" for errorCode.category().name() and "end of file" for errorCode.message()
If it claims to be in category asio.misc, then why does the if condition of (errorCode.category() == boost::asio::error::misc_category ) evaluate to false?
Googling (including answers here) says that a boost::system::error_code can have the same value in more than one category, so I assume that in order to get the proper message and meaning we must compare boost::system::error_category as well as boost::system::error_code::value.
How do we properly compare the category if this fails to work?
Code in question:
//--------------------------------------------------------------------------------------------------
std::string ClientSocketASIO::ErrorCodeToString(const boost::system::error_code & errorCode)
{
std::ostringstream debugMsg;
debugMsg << " Error Category: " << errorCode.category().name() << ". "
<< " Error Message: " << errorCode.message() << ". ";
if( errorCode.category() == boost::asio::error::misc_category )
{
switch (errorCode.value())
{
case boost::asio::error::eof:
debugMsg << ". Server has disconnected.";
break;
case boost::asio::error::connection_refused:
debugMsg << ". Connection Refused";
break;
default:
debugMsg << ". Unknown Error.";
break;
}
}
else
{
debugMsg << ". Unknown Error category.";
}
return debugMsg.str();
}
EDIT:
According to https://theboostcpplibraries.com/boost.system and Boost::file_system: Checking error codes
People commonly and mistakenly write code only comparing the error value and not the category. The error value alone is not unique and may occur in more than one category. Users are also free to create their own error codes and categories. Therefore, both must be compared. This, I assume, doesn't effect a large number of applications, because they are only using one feature or library of boost their project anyway and/or the majority of error codes are mapped to windows error codes which made a best effort to not collide.
I had to get on another computer to hit up the boost mailing list, since my work blocks almost everything.
http://boost.2283326.n4.nabble.com/Compare-boost-system-error-category-td4692861.html#a4692869
According to a fella over there, the reason the comparison is failing is because the boost library is statically linked, and boost::system::error_category::operator == compares addresses, so the LHS is the address in one lib and the RHS is the address in another. They are not going to be equal when they are expected to be.
Using the address for operator == seems like a very silly move to me. I will continue to rant about it on the boost mailing list and edit here for others if any new knowledge is discovered.
For now, I am dynamically link and use form
//--------------------------------------------------------------------------------------------------
std::string ClientSocketASIO::ErrorCodeToString(const boost::system::error_code & errorCode)
{
std::ostringstream debugMsg;
debugMsg << " Error Category: " << errorCode.category().name() << ". "
<< " Error Message: " << errorCode.message() << ". ";
// IMPORTANT - These comparisons only work if you dynamically link boost libraries
// Because boost chose to implement boost::system::error_category::operator == by comparing addresses
// The addresses are different in one library and the other when statically linking.
//
// We use make_error_code macro to make the correct category as well as error code value.
// Error code value is not unique and can be duplicated in more than one category.
if (errorCode == make_error_code(boost::asio::error::connection_refused))
{
debugMsg << ". Connection Refused";
}
else if (errorCode == make_error_code(boost::asio::error::eof))
{
debugMsg << ". Server has disconnected.";
}
else
{
debugMsg << ". boost::system::error_code has not been mapped to a meaningful message.";
}
return debugMsg.str();
}
however, this does not work when I link statically to boost either. If anyone has any more suggestions on how we are to properly compare boost::system::error_code and get expected results, please let's get to the bottom of this.
The C++ 11 standard implies that each error category instance shall have
a globally unique address and comparisons of equality shall use that
address to compare. Unfortunately, this is not reliable in portable
code, only the Dinkumware STL implements true address uniqueness
anywhere in the process and it adds a full memory barrier to achieve
that i.e. it's expensive.
Boost's quality of implementation is the same as libstdc++ or libc++,
you can get multiple instantiations in certain circumstances and those
can have differing addresses.
In my own code, I do the comparison operator first, and if that fails I
do a strcmp() of the category's name(). To date, this has not bitten me.
I would personally consider this aspect of error categories to be a
defect in the standard, as specified it forces non-header-only
implementation if you want it to be conforming, and even that doesn't
cover RTLD_LOCAL which means you need to fall back onto named shared
memory or some hack.

c++ error handling return values error returned

I have a class that I have been given some error input handling for. It's a class that has been given it's own "extraction" operator and I've been asked to implement the code that I've been given. The problem I'm having is that the code I should use looks similar to this.
try {
while (some condition)
{....implemented code....}
} catch (runtime_error& e) {
cerr << e.what() << endl;
return 1;
}
The problem I am having compiling this is it doesn't seem to like the "return 1" value it gives me an error of:
invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘int’
If I remove the return value it compiles straight but then the program fails to execute once it hits the area where it is trying to do the try statement. As mentioned the code I have there is the above is the example code we are supposed to implement so I assumed straight out of the box it would work. My condition for the while loop was
while (!std::cin.fail())
as I assumed I'd want to keep getting input until it fails for some reason. Why would the return values in this case be causing a problem?
Psychic debugging indicates:
your enclosing function has a signature of the form
std::istream& func_name(/*parameter list goes here*/)
Hence the compilation error

boost::program_options : iterating over and printing all options

I have recently started to use boost::program_options and found it to be highly convenient. That said, there is one thing missing that I was unable to code myself in a good way:
I would like to iterate over all options that have been collected in a boost::program_options::variables_map to output them on the screen. This should become a convenience function, that I can simply call to list all options that were set without the need to update the function when I add new options or for each program.
I know that I can check and output individual options, but as said above, this should become a general solution that is oblivious to the actual options. I further know that I can iterate over the contents of variables_map since it is simply an extended std::map. I could then check for the type containd in the stored boost::any variable and use .as<> to convert it back to the appropriate type. But this would mean coding a long switch block with one case for each type. And this doesn't look like good coding style to me.
So the question is, is there a better way to iterate over these options and output them?
As #Rost previously mentioned, Visitor pattern is a good choice here. To use it with PO you need to use notifiers for your options in such a way that if option is passed notifier will fill an entry in your set of boost::variant values. The set should be stored separately. After that you could iterate over your set and automatically process actions (i.e. print) on them using boost::apply_visitor.
For visitors, inherit from boost::static_visitor<>
Actually, I made Visitor and generic approach use more broad.
I created a class MyOption that holds description, boost::variant for value and other options like implicit, default and so on. I fill a vector of objects of the type MyOption in the same way like PO do for their options (see boost::po::options_add()) via templates. In the moment of passing std::string() or double() for boosts::variant initialization you fill type of the value and other things like default, implicit.
After that I used Visitor pattern to fill boost::po::options_description container since boost::po needs its own structures to parse input command line. During the filling I set notifyer for each option - if it will be passed boost::po will automatically fill my original object of MyOption.
Next you need to execute po::parse and po::notify. After that you will be able to use already filled std::vector<MyOption*> via Visitor pattern since it holds boost::variant inside.
What is good about all of this - you have to write your option type only once in the code - when filling your std::vector<MyOption*>.
PS. if using this approach you will face a problem of setting notifyer for an option with no value, refer to this topic to get a solution: boost-program-options: notifier for options with no value
PS2. Example of code:
std::vector<MyOptionDef> options;
OptionsEasyAdd(options)
("opt1", double(), "description1")
("opt2", std::string(), "description2")
...
;
po::options_descripton boost_descriptions;
AddDescriptionAndNotifyerForBoostVisitor add_decr_visitor(boost_descriptions);
// here all notifiers will be set automatically for correct work with each options' value type
for_each(options.begin(), options.end(), boost::apply_visitor(add_descr_visitor));
It's a good case to use Visitor pattern. Unfortunately boost::any doesn't support Visitor pattern like boost::variant does. Nevertheless there are some 3rd party approaches.
Another possible idea is to use RTTI: create map of type_info of known types mapped to type handler functor.
Since you are going to just print them out anyway you can grab original string representation when you parse. (likely there are compiler errors in the code, I ripped it out of my codebase and un-typedefed bunch of things)
std::vector<std::string> GetArgumentList(const std::vector<boost::program_options::option>& raw)
{
std::vector<std::string> args;
BOOST_FOREACH(const boost::program_options::option& option, raw)
{
if(option.unregistered) continue; // Skipping unknown options
if(option.value.empty())
args.push_back("--" + option.string_key));
else
{
// this loses order of positional options
BOOST_FOREACH(const std::string& value, option.value)
{
args.push_back("--" + option.string_key));
args.push_back(value);
}
}
}
return args;
}
Usage:
boost::program_options::parsed_options parsed = boost::program_options::command_line_parser( ...
std::vector<std::string> arguments = GetArgumentList(parsed.options);
// print
I was dealing with just this type of problem today. This is an old question, but perhaps this will help people who are looking for an answer.
The method I came up with is to try a bunch of as<...>() and then ignore the exception. It's not terribly pretty, but I got it to work.
In the below code block, vm is a variables_map from boost program_options. vit is an iterator over vm, making it a pair of std::string and boost::program_options::variable_value, the latter being a boost::any. I can print the name of the variable with vit->first, but vit->second isn't so easy to output because it is a boost::any, ie the original type has been lost. Some should be cast as a std::string, some as a double, and so on.
So, to cout the value of the variable, I can use this:
std::cout << vit->first << "=";
try { std::cout << vit->second.as<double>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<int>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<std::string>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<bool>() << std::endl;
} catch(...) {/* do nothing */ }
I only have 4 types that I use to get information from the command-line/config file, if I added more types, I would have to add more lines. I'll admit that this is a bit ugly.