Boost::file_system: Checking error codes - c++

Although I'm using C++11, this question is boost-related, since I'm processing errors from boost::file_system.
In the following situation:
try {
// If p2 doesn't exists, canonical throws an exception
// of No_such_file_or_directory
path p = canonical(p2);
// Other code
} catch (filesystem_error& e) {
if (e is the no_such_file_or_directory exception)
custom_message(e);
} // other catchs
}
If I print the error value when the desired exception (no_such_file_or_directory) is thrown:
// ...
} catch (filesystem_error& e) {
cout << "Value: " << e.code().value() << endl;
}
I get the value 2. It is the same value of e.code().default_error_condition().value().
My questions is: could different error conditions from different error categories have same values? I mean, does I need to check both, error categories and error values, in order to ensure I'm getting a specific error? In such a case, what is the cleanest way to do it?

error_codes and error_conditions with different error_categories are allowed to have the same value(). The non-member comparison functions check both the the value and category:
bool operator==( const error_code & lhs, const error_code & rhs ) noexcept;
Returns: lhs.category() == rhs.category() && lhs.value() == rhs.value().
Hence, the exceptions's error_code could be checked against the return from make_error_code(), such as follows:
try {
// If p2 doesn't exists, canonical throws an exception
// of No_such_file_or_directory
path p = canonical(p2);
// ...
} catch (filesystem_error& e) {
if (e.code() ==
make_error_code(boost::system::errc::no_such_file_or_directory)) {
custom_message(e);
}
}
Here is a complete example demonstrating two error_codes that are not equivalent despite having the same value:
#include <boost/asio/error.hpp>
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
int main()
{
// Two different error codes.
boost::system::error_code code1 = make_error_code(
boost::system::errc::no_such_file_or_directory);
boost::system::error_code code2 = make_error_code(
boost::asio::error::host_not_found_try_again);
// That have different error categories.
assert(code1.category() != code2.category());
assert(code1.default_error_condition().category() !=
code2.default_error_condition().category());
// Yet have the same value.
assert(code1.value() == code2.value());
assert(code1.default_error_condition().value() ==
code2.default_error_condition().value());
// Use the comparision operation to check both value
// and category.
assert(code1 != code2);
assert(code1.default_error_condition() !=
code2.default_error_condition());
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test with Boost.Filesytem
try
{
boost::filesystem::canonical("bogus_file");
}
catch(boost::filesystem::filesystem_error& error)
{
if (error.code() ==
make_error_code(boost::system::errc::no_such_file_or_directory))
{
std::cout << "No file or directory" << std::endl;
}
if (error.code() ==
make_error_code(boost::asio::error::host_not_found_try_again))
{
std::cout << "Host not found" << std::endl;
}
}
}
Which produces the following output:
No file or directory

Related

Rethrowing new exception with same message causes garbage output. Why?

I want to catch an exception to further specify the error message, then throw a new exception with that extended message. However, that causes garbage output. Why?
Here's an MWE:
#include <iostream>
#include <string>
#include <exception>
class myError : public std::exception
{
private:
std::string m_error;
public:
explicit myError( const std::string& error ) :
m_error { error }
{}
explicit myError( const char* error ) :
m_error { error }
{}
const char* what() const noexcept override
{
//return m_error.c_str();
return ("My error: " + m_error).c_str();
}
};
int main()
{
try{
try{
throw myError ( "Error message" );
} catch ( const std::exception& e ) {
throw myError( e.what() );
}
} catch ( const std::exception& e ) {
std::cout << e.what() << "\n";
}
return 0;
}
I would expect the output to be "My error: My error: Error message", but instead, it's a short sequence of random characters, presumably until a \0 is hit.
If I do not add a message inside myError::what() (i.e. the line that's commented out), then the output is simply "Error message", so everything works as expected.
Why is that happening?
I'm running gcc 8.1.0 on Windows, with x86_64-posix-seh-rev0 as the install options.
And I'm somewhat aware of nested_exception and that I'm losing some information on the trace etc.
EDIT: As a workaround, adding the message "My error" inside the constructor produces the expected output:
explicit myError( const std::string& error ) :
m_error { "My error: " + error }
{}
explicit myError( const char* error ) :
m_error { "My error: " + std::string{ error } }
{}
const char* what() const noexcept override
{
return m_error.c_str();
}
So something seems to be wrong with return ("My error: " + m_error).c_str();.
In:
return ("My error: " + m_error).c_str();
... c_str() returns a pointer to the internal buffer of the temporary string created by the concatenation. This string's lifetime ends immediately after the return statement, making the returned pointer dangling and its use undefined.

Under what circumstances does EXCEPTION_RECORD link to another nested exception?

The documentation for _EXCEPTION_RECORD says about one of it's members, struct _EXCEPTION_RECORD *ExceptionRecord
A pointer to an associated EXCEPTION_RECORD structure. Exception records can be chained together to provide additional information when nested exceptions occur.
However, I haven't been able to provoke such a situation of nested structured exceptions. Here is what I have tried so far:
#include <iostream>
#include <windows.h>
void Handle0(LPEXCEPTION_POINTERS pex) {
std::cout << "chain0 = " << pex->ExceptionRecord->ExceptionRecord << std::endl;
}
void Handle1(LPEXCEPTION_POINTERS pex) {
std::cout << "chain1 = " << pex->ExceptionRecord->ExceptionRecord << std::endl;
__try {
throw 3;
} __except( Handle0(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER ) {}
}
int main() {
__try {
throw 3;
} __except( Handle1(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER ) {}
return 0;
}
The pex->ExceptionRecord->ExceptionRecord is always nullptr. Under what circumstances do I get a link to a nested _EXCEPTION_RECORD there?
According to MSDN:
When an exception is raised during the processing of an exception
filter within ... native code ... a nested exception is raised, the
ExceptionRecord field in the EXCEPTION_RECORD structure (as returned
by GetExceptionInformation) is set, and the ExceptionFlags field sets
the 0x10 bit. The following example illustrates this difference in
behavior:
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#ifndef false
#define false 0
#endif
int *p;
int filter(PEXCEPTION_POINTERS ExceptionPointers) {
PEXCEPTION_RECORD ExceptionRecord =
ExceptionPointers->ExceptionRecord;
if ((ExceptionRecord->ExceptionFlags & 0x10) == 0) {
// not a nested exception, throw one
*p = 0; // throw another AV
}
else {
printf("Caught a nested exception\n");
return 1;
}
assert(false);
return 0;
}
void f(void) {
__try {
*p = 0; // throw an AV
}
__except(filter(GetExceptionInformation())) {
printf_s("We should execute this handler if "
"compiled to native\n");
}
}
int main() {
__try {
f();
}
__except(1) {
printf_s("The handler in main caught the "
"exception\n");
}
}
I believe it is also set if you try to continue non-continuable exception. In this case EXCEPTION_RECORD will represent EXCEPTION_NONCONTINUABLE_EXCEPTION, while its ExceptionRecord will point to original exception.

C++ catch error and exit the function

I use try{} catch(){} to handle errors in a function which return a template type.
T get (int iOffset) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return a;
}
The function would first call checkIndex to check whether the input is out of range and throw an error if so.
However, I don't want the outside get return any value if checkIndex throws an error, because the returned value may be used by other functions or printed out incorrectly. If I put a return in the catch block, I don't know what to return since it's a template. If I don't, the codes following the catch block will still get executed and therefore return a value.
Is there any way to do that? I'm new to C++ and wondering how people usually do the error handling in this condition? THanks!
However, I don't want the outside get return any value if checkIndex throws an error, because the returned value may be used by other functions or printed out incorrectly.
You can always re-throw the exception after logging
T get (int iOffset) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
throw; // Just re-throw the exception
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return a;
}
You can also use optional for this situation. One of idea of this construct was to indicate that value cannot be set correctly because of some mistakes.
std::optional< T > get (int iOffset ) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
return std::optional< T >();
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return return std::optional< T >( a );
}
Using of such function can look like this:
auto result = get( someOffset );
if( result )
{
// correct, processing result
}
One of the easiest way is first to decide: What exactly should your get() return if it cannot return the 'proper' value?
In many cases it is just 0, or -1, or some other special value.
And then the code become very simple:
T get (int iOffset) const
{
T a;
try {
checkIndex(iOffset);
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
a = m_ptBuff[index];
}
catch (char const* msg) {
a = special_value_for_errors;
std::cout << msg << std::endl;
}
return a;
}

Adding pairs to a vector C++

So, I'm attempting to add pairs to a vector, but they must successfully pass 2 criteria:
Their weight or 2nd value is greater than or equal to zero. and throws a string error if it does.
The vector must not already contain the key or the first value
It specifically must be done while the function returns a void type, however for some reason, this logic doesn't seem to be working. Any suggestions?
void add(KEY_T key, WEIGHT_T weight)
{
bool contains = false;
if (weight < 0)
{
std::cout << "ERROR, invalid weight" << std::endl; //Throw error.
}
for (int x = 0; x < _valueToWeightMap.size(); x++)
{
if (_valueToWeightMap[x].first == key)
{
contains = true;
}
}
if (weight > 0 && contains == false)
{
_valueToWeightMap.push_back(std::make_pair(key, weight));
}
}
Here is the main:
int main()
{
DiscreteDistribution<std::string> dist1;
dist1.add("Helmet", -1);
dist1.add("Gloves", 5);
dist1.add("Gloves", 5);
dist1.add("cloud", 8);
For some reason, I'm not getting an error when I try to add Helmet as -1. Any suggestions?
This line:
std::cout << "ERROR, invalid weight" << std::endl; //Throw error.
does not do what the comment says (throw an error). This line:
throw "ERROR, invalid weight"; //Throw error.
does. However, I strongly recommend that you only ever throw exceptions derived from std::exception. This:
throw std::range_error("ERROR, invalid weight"); //Throw error.
is much better.

Error checking on many function calls

Sometimes when I am programming in C++/C I end up calling the same function multiple times and I was wondering what is the most efficient way to check for errors for all of those calls? Using if else statements take up a lot of code and look ugly. I have come up with my own way of checking for errors, perhaps there is a better way that I should use.
int errs[5] = {0};
errs[0] = functiona(...);
errs[1] = functiona(...);
...
errs[5] = functiona(...);
for (int i = 0; i < 5; i++)
{
if (err[i] == 0)
MAYDAY!_wehaveanerror();
}
Note: I understand that using try and catch might be better for C++ as it would solve this problem by throwing an exception on the first error, but the problem with that is that it is not compatible with a lot of functions that return error codes such as the Windows API. Thanks!
You could write some pseudo-C++ like this:
struct my_exception : public std::exception {
my_exception(int); /* ... */ };
int main()
{
try
{
int e;
if ((e = function()) != SUCCESS) { throw my_exception(e); }
if ((e = function()) != SUCCESS) { throw my_exception(e); }
if ((e = function()) != SUCCESS) { throw my_exception(e); }
}
catch (my_exception & e)
{
std::cerr << "Something went wrong: " << e.what() << "\n";
}
}
If...IF the function has a chance to throw a different error you should also add a catch all.
struct my_exception : public std::exception {
my_exception(int); /* ... */ };
int main()
{
try
{
int e;
if ((e = function()) != SUCCESS) { throw my_exception(e); }
if ((e = function()) != SUCCESS) { throw my_exception(e); }
if ((e = function()) != SUCCESS) { throw my_exception(e); }
}
catch (my_exception & e)
{
std::cerr << "Something went wrong: " << e.what() << "\n";
}
catch (...)
{
//Error Checking
}
}
What about handling the checking in a function?
void my_function() {
if (!create_window())
throw Error("Failed to create window");
}
int main() {
try {
my_function();
} catch (const Error& e) {
cout << e.msg << endl;
} catch (...) {
cout << "Unknown exception caught\n"
}
return 0;
}
If you're calling the same function over and over again, the most succinct way might be to use a macro. I would suggest something like:
#define CHECKERROR(x) if(x == 0) wehaveanerror()
CHECKERROR(function(...));
CHECKERROR(function(...));
Obviously, this macro would be very specific to the particular function and error handler involved, so it may be prudent to undef it after those calls.
Doing it more old-school, but keeping w/ the original error response but responding as soon as an error occurs w/o looking ugly:
#define callcheck(r) if ((r)==0) MAYDAY!_wehaveanerror()
callcheck(functiona(...));
callcheck(functiona(...));
...