My C++ function has many if statements checking the returning value of called functions:
Result func(...){
if (SUCCESS != func1(...))
return ERROR;
// do something
if ( SUCCESS != func2(...))
return ERROR;
// do something else
if (SUCCESS != func3(...))
return ERROR;
// do something
.
.
.
}
Is there anyway for eliminating or reducing the if statements here?
For example I want something like this:
Result func(...){
Result result = SUCCESS;
when (result != SUCCESS) return ERROR;
result = func1(...);
// do something
result = func2(...);
// do something else
result = func3(...);
// do something
.
.
.
}
I cannot help myself, but to write solution which might be considered over-engineering, but it allows to prepare single template class for all results (for future use) and then minimize code for actual usage (no need to use checking methods or macros, no need to write own wrappers except this single result holder template class). Enjoy :D.
#include <iostream>
template<class T>
class Result
{
public:
Result() :
m_value(),
m_badValue()
{
}
Result(const T& value, const T& badValue) :
m_value(value),
m_badValue(badValue)
{
}
void operator=(const T& value)
{
if(value == m_badValue)
{
throw "Bad Value!";
}
else
{
m_value = value;
}
}
operator const T&() const
{
return m_value;
}
const T& value() const
{
return m_value;
}
private:
T m_value;
T m_badValue;
};
static const int SUCCESS = 0;
static const int FAIL = -1;
int func1()
{
return SUCCESS;
}
int func2()
{
return SUCCESS;
}
int func3()
{
return FAIL;
}
int main()
{
Result<int> result(FAIL, FAIL);
try
{
result = func1();
result = func2();
result = func3();
}
catch (const char *error)
{
::std::cout << "Error: " << error << ::std::endl;
}
::std::cout << "Last value: " << static_cast<int>(result) << " - " <<
((result == SUCCESS) ? "SUCCESS" : "FAIL") << ::std::endl;
}
Note: you should throw only what derives from ::std::exception, but I used const char* to simplify things and prepare working example.
Since you are coding in C++, not in C, the option of throwing exceptions is available to you. Making the code look better while responding to exceptional situations properly was the primary driving force behind the feature.
In situations when you use third-party APIs that do not offer exceptions you could wrap their functions into your functions that throw exceptions, like this:
void func1w(...) {
if (SUCCESS!=func1(...)) throw my_exception();
}
void func2w(...) {
if (SUCCESS!=func2(...)) throw my_exception();
}
...
void caller() {
try {
func1w();
func2w();
func3w();
} catch (my_exception& e) {
cerr << "Error!" << endl;
}
}
Note that the function that calls exception-throwing wrappers could stay away from checking exception codes altogether, letting the higher-level function deal with them. The general rule with exceptions is that the code should not catch exceptions unless it knows how to handle them.
You can also define a macro:
#define MUST_SUCCEED(x) if(SUCCESS!=(x))return ERROR
This comes at the cost of reduced readability, because the macro is not instantly familiar to the readers of your code:
MUST_SUCCEED(func1(...));
MUST_SUCCEED(func2(...));
MUST_SUCCEED(func3(...));
Short answer: no
Long answer: no, that's how you do it in every structured programming language that I'm aware of.
Alternative: if all functions involved (func1, func2, func3) would throw exceptions instead of returning a status code then you wouldn't have to use ifs. Your function func would just propagate any exception that was thrown from within it.
Edit, expanding on Tony's comment:
Alternative #2: involved functions do not throw exceptions, but your function could. Suppose you have a helper function like this:
void CheckResult(Result result)
{
if (result != SUCCESS)
throw SomeException(result);
}
Your function would then look like this:
void func(...)
{
CheckResult(func1(...));
// do something
CheckResult(func2(...));
// do something else
CheckResult(func3(...));
// do something
}
So, the if's are not avoided but moved to another function, so that your function is free of them.
You could make a vector of function pointers containing func1(), func2() etc., then iterate through all the elements in this vector by means of for loop, calling each function and comparing the value returned against SUCCESS. Then, if the return value of any function does not equal SUCCESS, you can set a flag to a value indicating error (in your example this flag would be of the name 'result').
Related
I have a class interface function which implements other functions within the class in a specific order:
class Child
{
public:
auto Interface()->bool
{
this->F1(); //I use this just for extra clarity (e.g. not calling global function)
this->F2();
return true;
}
auto F1()->void
{
//Do stuff...
}
auto F2()->void
{
//Do more stuff...
}
};
class Parent
{
public:
Child ChildObj;
auto CallUponChild()->void
{
bool success = ChildObj.Interface();
}
};
I want to wrap the 'Interface()' implementation in a try/catch block:
auto Interface()->bool
{
try{
this->F1();
this->F2();
}catch(...){
//Handle
}
}
However, on the occurance of an error, I wish to attempt the function again, and if that errors, I want to propogate the error back to the Parent class:
auto Interface()->bool
{
int error_count=0;
try{
try{
this->F1();
this->F2();
return true;
}catch(...){
if(error_count<1){this->F1(); this->F2();}
else{throw "Out of tries";}
}
}catch(...){
return false;
}
}
Is using nested try/catch blocks fround upon? Is this the best approach to take?
Something like
auto Interface()->bool
{ int error_count=0;
while (error_count < 1) {
try {
this->F1();
this->F2();
return true;
}
catch(...){
// if (error_count >= 1)
// throw; // to throw original exception
++error_count;
}
};
// throw "Out of tries"; // to throw "Out of tries" exception
return false; // to use the boolean result
}
should be sufficient. If F1() throws an exception in your catch block, your function will return false without incrementing error_count.
It does not seems to be something that the child should handle imho, should that behaviour been handled by the Parent which knows how to deal with their childs? I would go this way:
auto CallUponChild()->void
{
const bool success = ChildObj.Interface();
if (!success) { // maybe if-init if you have a c++17 compiler
// try again
ChildObj.Interface();
}
}
I think the way to handle the child objects should be at Parent level as I said, Child object should do one thing and if it's needed to be done twice(or N) then should'n be their responsibility.
If you want to show how the exception were thrown you can have a look at this:
http://en.cppreference.com/w/cpp/error/throw_with_nested
I have a C++ class which throws an exception from the constructor on failure. How can I allocate a local instance of this class (without using new) and handle any possible exceptions, while keeping the try block scope as small as possible?
Essentially, I am looking for the C++ equivalent of the following Java idiom:
boolean foo() {
Bar x;
try {
x = new Bar();
} catch (Exception e) {
return false;
}
x.doSomething();
return true;
}
I do not want to catch exceptions from x.doSomething(), only the constructor.
I suppose what I'm looking for is a way to separate the declaration and the initialization of x.
Is it possible to accomplish this without using heap allocations and pointers?
You can use std::optional from C++17:
bool foo() {
std::optional<Bar> x; // x contains nothing; no Bar constructed
try {
x.emplace(); // construct Bar (via default constructor)
} catch (const Exception& e) {
return false;
}
x->doSomething(); // call Bar::doSomething() via x (also (*x).doSomething() )
return true;
}
This Java idiom doesn't translate well to C++ since Bar x; will require default constructor even if your real constructor requires arguments to be passed.
I'd advise fighting the language to this degree - widening the try block is sufficient - but if you really want to narrow then you could use a function and rely on return value optimisation to obviate a value copy:
Bar foobar()
{
try {
return Bar();
} catch (Exception& e){
/* Do something here like throwing a specific construction exception
which you intercept at the call site.*/
}
}
But really, you could throw a specific exception on construction, so obviating this function approach entirely.
Yes it's possible, if you put all the code in the try clause, for example by using a function try block (to avoid unnecessary nesting and scoping):
bool foo() try
{
Bar x;
x.doSomething();
return true;
}
catch (std::exception const& e)
{
return false;
}
Or in the try clause call another function which does the real work:
void real_foo()
{
Bar x;
x.doSomething();
}
bool foo() try
{
real_foo();
return true;
}
catch (std::exception const& e)
{
return false;
}
Note that it's often not a good idea to throw exceptions in a constructor, as that will halt the construction of the object, and its destructor will not be called.
As noted by Holt, this will also catch exceptions from the doSomething call. There are two ways of solving that:
The simple and standard way: Use pointers.
Use two-stage construction: Have a default constructor which can't throw exceptions, then call a special "construct" function that can throw exceptions.
The second way was common before C++ was standardized, and used extensively in code for the Symbian system. It is not common any more since using pointers for this is much more easy and simpler, especially today with good smart pointers available. I really don't recommend the second way in modern C++.
The easiest way is of course to make sure that the constructor can't throw exceptions at all, or if any is thrown then they are of the nature that the program can't continue anyway and have the program be terminated. As noted in the comments to your question, exceptions in C++ are expensive, and then we also have the abandoned construction issue, and in all using exceptions in C++ should only be done in exceptional cases. C++ is not Java, you should not treat it as such even if there are similar constructs in both languages.
If you still want to throw exceptions from the constructor there is actually a third way to catch only those: Use one of the code-example up top, and throw only specific exceptions that doSomething can never throw and then catch these specific constructors only.
Normally if you want to avoid heap allocations, you can't separate the declaration of a local variable from its definition. So if you were to combine everything in a single function, you would have to do surround the entire scope of x with try/catch block:
boolean foo() {
try {
Bar x;
x.doSomething();
} catch (Exception e) {
return false;
}
return true;
}
No. From your java example, you will have to choose between these 2 possibilities:
Without pointers:
bool foo() {
try {
Bar x;
x.doSomething();
} catch (Exception e) {
return false;
}
return true;
}
With pointers:
bool foo() {
Bar* x = nullptr;
try {
x = new Bar();
} catch (Exception e) {
return false;
}
x->doSomething();
delete x; // don't forget to free memory
return true;
}
Or using managed pointers:
#include <memory>
bool foo() {
std::unique_ptr<Bar> x;
try {
x = new Bar(); // until C++14
x = std::make_unique<Bar>(); // since C++14
} catch (Exception e) {
return false;
}
x->doSomething();
return true;
}
You have to choose between variant of
bool foo() {
std::unique_ptr<Bar> x;
try {
x = std::make_unique<Bar>();
} catch (const BarConstructorException& e) {
return false;
}
x->doSomething();
return true;
}
or
bool foo() {
try {
Bar x;
x.doSomething();
} catch (const BarConstructorException& e) {
return false;
}
return true;
}
In the revised question the OP adds the requirement that
” I do not want to catch exceptions from x.doSomething(), only the constructor [of the local variable].
A simple way to translate the Java code
boolean foo() {
Bar x;
try {
x = new Bar();
} catch (Exception e) {
return false;
}
x.doSomething();
return true;
}
… to C++, is then to use an Optional_ class (like Barton-Nackmann Fallible, boost::optional or C++17 std::optional)
auto foo()
-> bool
{
Optional_<Bar> xo;
try
{
xo.emplace();
}
catch( ... )
{
return false;
}
Bar& x = *xo;
// Possibly other code here, then:
x.doSomething();
return true;
}
A nice alternative is to refactor that code, like this:
struct Something_failure {};
void do_something( Bar& o )
{
// Possibly other code here, then:
o.doSomething();
}
auto foo()
-> bool
{
try
{
Bar x;
do_something( x );
return true;
}
catch( Something_failure const& )
{
throw;
}
catch( ... )
{}
return false;
}
If you do not like the above approaches then you can always go for a dynamically allocated Bar instance, e.g. using a std::unique_ptr for guaranteed cleanup, which however has the general overhead of a dynamic allocation. In Java most every object is dynamically allocated so that might not seem to be a serious disadvantage. But in C++ most objects are superfast stack-allocated so that a dynamic allocation is a very slow operation compared to ordinary operations, so the possible conceptual simplicity of dynamic allocation must be weighted against that.
Our Python codebase has metrics-related code that looks like this:
class Timer:
def __enter__(self, name):
self.name = name
self.start = time.time()
def __exit__(self):
elapsed = time.time() - self.start
log.info('%s took %f seconds' % (self.name, elapsed))
...
with Timer('foo'):
do some work
with Timer('bar') as named_timer:
do some work
named_timer.some_mutative_method()
do some more work
In Python's terminology, the timer is a contextmanager.
Now we want to implement the same thing in C++, with an equally nice syntax. Unfortunately, C++ doesn't have with. So the "obvious" idiom would be (classical RAII)
class Timer {
Timer(std::string name) : name_(std::move(name)) {}
~Timer() { /* ... */ }
};
if (true) {
Timer t("foo");
do some work
}
if (true) {
Timer named_timer("bar");
do some work
named_timer.some_mutative_method();
do some more work
}
But this is extremely ugly syntactic salt: it's many lines longer than it needs to be, we had to introduce a name t for our "unnamed" timer (and the code breaks silently if we forget that name)... it's just ugly.
What are some syntactic idioms that people have used to deal with "contextmanagers" in C++?
I've thought of this abusive idea, which reduces the line-count but doesn't get rid of the name t:
// give Timer an implicit always-true conversion to bool
if (auto t = Timer("foo")) {
do some work
}
Or this architectural monstrosity, which I don't even trust myself to use correctly:
Timer("foo", [&](auto&) {
do some work
});
Timer("bar", [&](auto& named_timer) {
do some work
named_timer.some_mutative_method();
do some more work
});
where the constructor of Timer actually invokes the given lambda (with argument *this) and does the logging all in one go.
Neither of those ideas seems like a "best practice", though. Help me out here!
Another way to phrase the question might be: If you were designing std::lock_guard from scratch, how would you do it so as to eliminate as much boilerplate as possible? lock_guard is a perfect example of a contextmanager: it's a utility, it's intrinsically RAII, and you hardly ever want to bother naming it.
It's possible to mimic the Python syntax and semantics quite closely. The following test case compiles and has largely similar semantics to what you'd have in Python:
// https://github.com/KubaO/stackoverflown/tree/master/questions/pythonic-with-33088614
#include <cassert>
#include <cstdio>
#include <exception>
#include <iostream>
#include <optional>
#include <string>
#include <type_traits>
[...]
int main() {
// with Resource("foo"):
// print("* Doing work!\n")
with<Resource>("foo") >= [&] {
std::cout << "1. Doing work\n";
};
// with Resource("foo", True) as r:
// r.say("* Doing work too")
with<Resource>("bar", true) >= [&](auto &r) {
r.say("2. Doing work too");
};
for (bool succeed : {true, false}) {
// Shorthand for:
// try:
// with Resource("bar", succeed) as r:
// r.say("Hello")
// print("* Doing work\n")
// except:
// print("* Can't do work\n")
with<Resource>("bar", succeed) >= [&](auto &r) {
r.say("Hello");
std::cout << "3. Doing work\n";
} >= else_ >= [&] {
std::cout << "4. Can't do work\n";
};
}
}
That's given
class Resource {
const std::string str;
public:
const bool successful;
Resource(const Resource &) = delete;
Resource(Resource &&) = delete;
Resource(const std::string &str, bool succeed = true)
: str(str), successful(succeed) {}
void say(const std::string &s) {
std::cout << "Resource(" << str << ") says: " << s << "\n";
}
};
The with free function passes all the work to the with_impl class:
template <typename T, typename... Ts>
with_impl<T> with(Ts &&... args) {
return with_impl<T>(std::forward<Ts>(args)...);
}
How do we get there? First, we need a context_manager class: the traits class that implements the enter and exit methods - the equivalents of Python's __enter__ and __exit__. As soon as the is_detected type trait gets rolled into C++, this class can also easily forward to the compatible enter and exit methods of the class type T, thus mimicking Python's semantics even better. As it stands, the context manager is rather simple:
template <typename T>
class context_manager_base {
protected:
std::optional<T> context;
public:
T &get() { return context.value(); }
template <typename... Ts>
std::enable_if_t<std::is_constructible_v<T, Ts...>, bool> enter(Ts &&... args) {
context.emplace(std::forward<Ts>(args)...);
return true;
}
bool exit(std::exception_ptr) {
context.reset();
return true;
}
};
template <typename T>
class context_manager : public context_manager_base<T> {};
Let's see how this class would be specialized to wrap the Resource objects, or std::FILE *.
template <>
class context_manager<Resource> : public context_manager_base<Resource> {
public:
template <typename... Ts>
bool enter(Ts &&... args) {
context.emplace(std::forward<Ts>(args)...);
return context.value().successful;
}
};
template <>
class context_manager<std::FILE *> {
std::FILE *file;
public:
std::FILE *get() { return file; }
bool enter(const char *filename, const char *mode) {
file = std::fopen(filename, mode);
return file;
}
bool leave(std::exception_ptr) { return !file || (fclose(file) == 0); }
~context_manager() { leave({}); }
};
The implementation of the core functionality is in the with_impl type. Note how the exception handling within the suite (the first lambda) and the exit function mimic Python behavior.
static class else_t *else_;
class pass_exceptions_t {};
template <typename T>
class with_impl {
context_manager<T> mgr;
bool ok;
enum class Stage { WITH, ELSE, DONE } stage = Stage::WITH;
std::exception_ptr exception = {};
public:
with_impl(const with_impl &) = delete;
with_impl(with_impl &&) = delete;
template <typename... Ts>
explicit with_impl(Ts &&... args) {
try {
ok = mgr.enter(std::forward<Ts>(args)...);
} catch (...) {
ok = false;
}
}
template <typename... Ts>
explicit with_impl(pass_exceptions_t, Ts &&... args) {
ok = mgr.enter(std::forward<Ts>(args)...);
}
~with_impl() {
if (!mgr.exit(exception) && exception) std::rethrow_exception(exception);
}
with_impl &operator>=(else_t *) {
assert(stage == Stage::ELSE);
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<void, Fn, decltype(mgr.get())>, with_impl &>
operator>=(Fn &&fn) {
assert(stage == Stage::WITH);
if (ok) try {
std::forward<Fn>(fn)(mgr.get());
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<bool, Fn, decltype(mgr.get())>, with_impl &>
operator>=(Fn &&fn) {
assert(stage == Stage::WITH);
if (ok) try {
ok = std::forward<Fn>(fn)(mgr.get());
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<void, Fn>, with_impl &> operator>=(Fn &&fn) {
assert(stage != Stage::DONE);
if (stage == Stage::WITH) {
if (ok) try {
std::forward<Fn>(fn)();
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
} else {
assert(stage == Stage::ELSE);
if (!ok) std::forward<Fn>(fn)();
if (!mgr.exit(exception) && exception) std::rethrow_exception(exception);
stage = Stage::DONE;
}
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<bool, Fn>, with_impl &> operator>=(Fn &&fn) {
assert(stage != Stage::DONE);
if (stage == Stage::WITH) {
if (ok) try {
ok = std::forward<Fn>(fn)();
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
} else {
assert(stage == Stage::ELSE);
if (!ok) std::forward<Fn>(fn)();
if (!mgr.exit(exception) && exception) std::rethrow_exception(exception);
stage = Stage::DONE;
}
return *this;
}
};
Edit: After reading Dai's comment more carefully, and thinking a bit more, I realized this is a poor choice for C++ RAII. Why? Because you are logging in the destructor, this means you are doing io, and io can throw. C++ destructors should not emit exceptions. With python, writing a throwing __exit__ isn't necessarily awesome either, it can cause you to drop your first exception on the floor. But in python, you definitively know whether the code in the context manager has caused an exception or not. If it caused an exception, you can just omit your logging in __exit__ and pass through the exception. I leave my original answer below in case you have a context manager which doesn't risk throwing on exit.
The C++ version is 2 lines longer than the python version, one for each curly brace. If C++ is only two lines longer than python, that's doing well. Context managers are designed for this specific thing, RAII is more general and provides a strict superset of the functionality. If you want to know best practice, you already found it: have an anonymous scope and create the object at the beginning. This is idiomatic. You may find it ugly coming from python, but in the C++ world it's just fine. The same way someone from C++ will find context managers ugly in certain situations. FWIW I use both languages professionally and this doesn't bother me at all.
That said, I'll provide a cleaner approach for anonymous context managers. Your approach with constructing Timer with a lambda and immediately letting it destruct is pretty weird, so you're right to be suspicious. A better approach:
template <class F>
void with_timer(const std::string & name, F && f) {
Timer timer(name);
f();
}
Usage:
with_timer("hello", [&] {
do something;
});
This is equivalent to the anonymous context manager, in the sense that none of Timer's methods can be called other than construction and destruction. Also, it uses the "normal" class, so you can use the class when you need a named context manager, and this function otherwise. You could obviously write with_lock_guard in a very similar way. There it's even better as lock_guard doesn't have any member functions you're missing out on.
All that said, would I use with_lock_guard, or approve code written by a teammate that added in such a utility? No. One or two extra lines of code just doesn't matter; this function doesn't add enough utility to justify it's own existence. YMMV.
You don't need if( true ), C++ has "anonymous scopes" which can be used to restrict a scope's lifetime in much the same was as Python's with or C#s using (well, C# also has anonymous scopes too).
Like so:
doSomething();
{
Time timer("foo");
doSomethingElse();
}
doMoreStuff();
Just use bare curly-brackets.
However, I disagree with your idea of using RAII-semantics to instrument code like this as the timer destructor is non-trivial and has side-effects by-design. It might be ugly and repetitive, but I feel explicitly calling named startTimer, stopTimer and printTimer methods make the program more "correct" and self-documenting. Side-effects are bad, m'key?
I have recently started a C++ project to mimic Python's context manager as I migrate a python code base over to C++, found at https://github.com/batconjurer/contextual.
For this flow, you need to define a resource manager derived from an interface named IResource. Below, this is called Timer. It is in this class that the enter and exit functions are implemented. The context is just the code block that requires the resources, so it is passed via anonymous function.
The resource manager expects you to implement the IData struct which is uses to store the acquired resources. It actually only keeps a pointer to an IData instance.
For your use case, the following is an example implementation that compiles with C++17.
#include "include/contextual.h"
#include <ctime>
#include <chrono>
#include <thread>
using namespace Contextual;
namespace Contextual {
struct IData {
std::string name;
std::time_t start_time = std::time(NULL);
void reset_time() {
std::cout << "Time before restart: " << start_time << "\n";
std::time(&start_time);
std::cout << "Time after restart: " << start_time << "\n";
};
};
class Timer : public IResource<IData> {
private:
IData _data;
void enter() override {
std::time(&resources->start_time);
}
void exit(std::optional<std::exception> e) override {
double elapsed_time = std::time(NULL) - resources->start_time;
std::cout << resources->name << " took " << elapsed_time << " seconds.\n";
if (e) {
throw e.value();
}
}
public:
Timer(std::string &&name) : IResource<IData>(_data), _data(IData{name}){};
};
};
int main(){
With {
Timer(std::string("Foo")) + Context{
[&](IData* time_data) {
std::chrono::milliseconds sleeptime(5000);
std::this_thread::sleep_for(sleeptime); // In place of "Do some work"
time_data->reset_time(); // In place of "some_mutative_function()"
std::this_thread::sleep_for(sleeptime); // In place of "Do some work"
}
}
};
}
There are some nuisances I'm still working on (for example the fact that the IData struct had to be stored as a instance variable of the Timer since only a pointer to it is kept by IResource). And of course C++ exceptions aren't the nicest things.
Inspired by Dai's answer, I ended up with this code:
#include <iostream>
#include <chrono>
class Timer
{
std::chrono::high_resolution_clock::time_point startTime;
public:
Timer(): startTime(std::chrono::high_resolution_clock::now()){};
void elapsed()
{
auto endTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsedTime = endTime - startTime;
std::cout << elapsedTime.count() << std::endl;
}
};
int main()
{
{
Timer timer=Timer();
std::cout << "This is some work" << std::endl;
timer.elapsed();
}
return 0;
}
I'm much more fluent in python than in c++; I'm not sure if it's idiomatic but it works for me.
I have an exception class called Exception, and I'm invoking a recursive function which gets called approximately 200 times while looping through a map. RecursiveFunction() is part of a class that contains a parameters map (which maps a string to a class param). The class param contains a min, a max, and number of steps between min and max, so that a set of functions can be run with each parameter set. RecursiveFunction() therefore loops through the map to run a set of functions given the 'current' parameters.
bool RecursiveFunction(map<string,param>::iterator current) {
map<string,param>::iterator last = parameters.end();
last--;
if( current == last )
return true;
else {
// Do some things
if(something_wrong)
throw Exception("RecursiveFunction()","Something went wrong");
++current;
RecursiveFunction(current);
}
}
The code above fails after about 120 recursive calls. It seems to be a memory issue, because most of the time it fails on the line:
last--;
The weird thing is that the code runs smoothly in both of the following cases:
bool RecursiveFunction(map<string,param>::iterator current) {
...
if(something_wrong)
throw "";
...
}
or
bool RecursiveFunction(map<string,param>::iterator current) {
...
if(something_wrong) {
Exception exc = Exception("RecursiveFunction()","Something went wrong");
ThrowException(exc); //ThrowException() { throw exc; }
}
...
}
The code isn't hitting the 'throw' so the Exception is not being constructed or copied (confirmed with breakpoints). Why would the existence of a class affect the outcome of a function, if that class isn't getting instantiated in the function?
EDIT:
I was able to reproduce this using a complete example (with Visual Studio 2010):
#include <iostream>
using namespace std;
class Exception: public std::exception {
private:
char gsCallPath[1001];
char gsError[1001];
public:
Exception(const char* sErrorCallPath, const char* sThrownError)
{
strcpy(gsError,sThrownError);
strcpy(gsCallPath,sErrorCallPath);
}
~Exception() {
}
};
bool RecursiveFunction(int n);
int main() {
RecursiveFunction(500);
}
bool RecursiveFunction(int n) {
cout << n << '\n';
if (n == 0)
return true;
else {
if(false) {
throw Exception("","");
//throw "";
}
else
{
RecursiveFunction( n-1 );
}
}
}
The run crashed with a Stack Overflow exception. Replacing throw Exception("",""); with throw ""; allowed the program to run to completion. Note: the size of the Exception class had an impact on how big n needed to be in order to overflow. Thanks #catscradle and #Yakk for your comments.
#include <exception>
void f() {
if (false) {
throw "";
//throw std::exception();
}
return f();
}
int main() {
f();
}
Looking at the assembly, it seems that the function reserves stack space for the exception object and it doesn't matter if it gets thrown or not. So in case of "" this function reserves 204 bytes(sub esp, 0CCh) and in case of std::exception it's sub esp, 0D4h, i.e. 8 bytes more, which is sizeof(std::exception) - sizeof(char*).
I have recently started using boost::exception. Now I would like to use boost::errinfo_nested_exception to print information about the cause of the error. The problem is I can't figure out how to get information from the cause. I have tried the following with no success:
#include <iostream>
#include <boost/exception/all.hpp>
struct myex : public virtual boost::exception {};
int main()
{
myex cause;
cause << boost::errinfo_file_name("causefile.cpp");
try {
myex ex;
ex << boost::errinfo_nested_exception(boost::copy_exception(cause));
throw ex;
}
catch (myex& e) {
// Here I would like to extract file name from cause and print
// it in a nice way, but I cant figure out what to do with a
// boost::exception_ptr.
const boost::exception_ptr* c =
boost::get_error_info<boost::errinfo_nested_exception>(e);
// I cant do this:
// const std::string* file = boost::get_error_info<boost::errinfo_file_name>(*c);
// Nor this:
// const std::string* file = boost::get_error_info<boost::errinfo_file_name>(**c);
// This works fine and the nested exception is there, but that's not what I want.
std::cout << boost::diagnostic_information(e) << std::endl;
}
return 0;
}
You need to rethrow the nested exception and examine that:
const boost::exception_ptr* c =
boost::get_error_info<boost::errinfo_nested_exception>(e);
if(c) try {
boost::rethrow_exception(*c);
} catch(boost::exception const& e) { // or a type derived from it
const std::string* file = boost::get_error_info<boost::errinfo_file_name>(e);
// ...
} catch(...) {
// presumably you don't want the exception to escape if it is
// not derived from boost::exception
}
I personally use a get_error_info wrapper that returns the result of boost::get_error_info<some_error_info>(e), or if nothing is found the result of get_error_info<some_error_info>(nested) (recursive call here) or 0 if there is no nested exception (or it is not error_info-enabled).
Alternatively/as a complement, you can factor the checking code above (the different catch clauses) in a function:
std::string const* // or return a tuple of what you examined etc.
examine_exception()
{
try {
throw; // precondition: an exception is active
} catch(boost::exception const& e) {
// as above
return ...;
}
}
boost::diagnostic_information is the correct way to get a description afaik.
But you could also overload to_string for boost::error_info(T):
http://svn.boost.org/svn/boost/trunk/boost/exception/errinfo_errno.hpp