Error checking on many function calls - c++

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(...));
...

Related

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;
}

How to assert that an error message equals to certain char expression

I am trying to call a function from my Calculator class in a test class.
How do I assert that exception message thrown by Calculator equals to one I expect?
My calculator code:
void Calculator::add() {
if (_stack.empty()) {
throw std::runtime_error("empty stack");
}
else if (_stack.size() == 1) {
throw std::runtime_error("Wrong Value");
}
else if (_stack.size() > 2) {
throw std::runtime_error("Wrong Value");
}
else {
double res = this->pop() + this->pop();
this->push(res);
}
}
Here is my test class:
TEST_METHOD(should_throw_error_if_stack_is_empty) {
Assert::AreEqual([] {
Calculator* myCalculator = new Calculator();
try {
myCalculator->add();
}
catch (std::runtime_error const& ex)
{
return (ex.what());
}
}, "empty stack");
}
The reason it does not work: Value returned by lambda function has type const char* while my expression type is const char. How should I do it?
And is the approach I follow a good practice in general? I mean catching the exceptions thrown by class in a unit test?

With Do Begin Statement in C++ Builder

I wanna know how to write the following codes in C++ Builder by using With Do Begin statement similar to Delphi.
I tried with ComboBox->Text .... do ... try and it's not working. I tried with just do ComboBox->Text .... try, also not working.
if (ComboBox->Text.operator==(String("C++ Builder XE7")))
{
try
{
// do something
if ((Form1->Memo1->Lines->Text).Pos("<") !=0)
{
// do something
}
}
catch(Exception &ex)
{
ShowMessage(ex.ToString());
}
if (ComboBox->Text.operator==(String("C++ Builder XE8")))
{
try
{
// do something
if ((Form1->Memo1->Lines->Text).Pos("<") !=0)
{
// do something
}
}
catch(Exception &ex)
{
ShowMessage(ex.ToString());
}
There is no equivalent to Delphi's with statement in C++. The best you can do in C++ is use pointers/references instead, eg:
TComboBox *cb = ComboBox;
TStrings *lines = Form1->Memo1->Lines;
if (cb->Text == "C++ Builder XE7")
{
try
{
// do something
if (lines->Text.Pos("<") != 0)
{
// do something
}
}
catch(const Exception &ex)
{
ShowMessage(const_cast<Exception&>(ex).ToString());
}
}
if (cb->Text == "C++ Builder XE8")
{
try
{
// do something
if (lines->Text.Pos("<") != 0)
{
// do something
}
}
catch(const Exception &ex)
{
ShowMessage(const_cast<Exception&>(ex).ToString());
}
}

Boost::file_system: Checking error codes

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

Error in exception handling with LLVM

I am trying to compile C++ code with CLANG++ as front end and backend as LLVM.
The version is 3.0.
There seems to be a problem with exception handling. Whenever the code throws an exception, the program just terminates with message that "Termination after throwing an exception".
Here is one of the sample code I tried with CLANG ++ .
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : virtual A {};
struct E : private B, public C, private D {};
extern "C" void abort ();
void fne (E *e)
{
throw e;
}
void check(E *e)
{
int caught;
caught = 0;
try { fne(e); }
catch(A *p) { caught = 1; if (p != e) abort();}
catch(...) { abort(); }
if (!caught) abort();
caught = 0;
try { fne(e); }
catch(B *p) { abort ();}
catch(...) { caught = 1; }
if (!caught) abort();
caught = 0;
try { fne(e); }
catch(C *p) { caught = 1; if (p != e) abort();}
catch(...) { abort(); }
if (!caught) abort();
caught = 0;
try { fne(e); }
catch(D *p) { abort ();}
catch(...) { caught = 1; }
if (!caught) abort();
return;
}
int main ()
{
E e;
check (&e);
check ((E *)0);
return 0;
}
I am quite new to LLVM so do not have much idea about it. Also does it have anything related to Exception Handling table generation by LLVM.
The above problem continues for any code.
I have compiled the above code on Linux machine.
Also I tried putting printf on every catch clause but no response. So it seems that when exception was thrown , no matching catch was found for the exception and it led to call of terminate funciton
Seeing your other question... If you're on arm/linux - then such result is expected. The support for EH is not finished there, so, it might be arbitrary broken.