I wrote a very simple solution however someone laughed and found a flaw as shown here http://ideone.com/IcWMEf
#include <iostream>
#include <ostream>
#include <functional>
#include <exception>
using namespace std;
// Wrong scope(failure)
class FailBlockT
{
typedef function<void()> T;
public:
T t;
FailBlockT(T t)
{
this->t=t;
}
~FailBlockT()
{
if (std::uncaught_exception())
{
t();
}
}
};
struct Test
{
~Test()
{
try
{
FailBlockT f([]()
{
cout << "failure" << endl;
});
// there is no any exception here, but "failure" is printed.
// See output below
}
catch(...)
{
cout << "some exception" << endl;
}
}
};
int main()
{
try
{
Test t;
throw 1;
}
catch(int){}
return 0;
}
In short the problem is my code looks at std::uncaught_exception(). When an exception is thrown and a normal destructor is executed. If i use scope failure there it will look at std::uncaught_exception() and think the object scope is lost due to exception rather then simply walking out of scope.
I can't think of any good solutions to differentiate leaving scope normally VS having an exception thrown IN it. Yes i know throwing is a bad idea in dtors BUT thats why I fail to notice this problem, because I never throw in exceptions.
How do I differentiate/solve this?
No exception was thrown but it thinks it has.
An exception was thrown, just not from right there.
There is no mechanism in C++11 to ask, "Was an exception thrown from code just below me, but not from code elsewhere in the call-stack?" std::uncaught_exception is doing exactly what it is supposed to do: say whether there is an exception currently in the process of being resolved at the time the function is called. And there is, so it returns true.
C++17 adds std::uncaught_exceptions (note the plural), which can be used to detect the difference. With such a tool, you can make your FailBlock object work:
template<typename Func>
class FailBlockT
{
private:
int e_count_;
T t_;
public:
FailBlockT(T t) : e_count_(std::uncaught_exceptions()), t_(t) {}
FailBlock(const FailBlock &) = delete; //The type should not be mobile.
~FailBlockT()
{
if (std::uncaught_exceptions() != e_count_)
{
t_();
}
}
};
std::uncaught_exceptions() returns the number of exceptions that are provoking stack unwinding at the time the call was made. If the number is the same during the constructor and destructor of an object (assuming it's a stack object), then the destructor is not being called due to an exception being thrown through where this type was used.
But without this tool, it, there's not much you can do to differentiate between an exception provoking the exiting of the scope rather than exiting a scope when exception unwinding just happens to be going on. So you're going to have to bite the bullet and catch the exception like everyone else.
Or just don't put this FailBlock thing in destructors. It seems to me that those should go directly into regular functions that can actually throw (and destructors should never throw). It seems to me that you're worried about a corner case that doesn't make any real sense.
I can't think of any good solutions to differentiate leaving scope normally VS having an exception thrown IN it.
Check stack_unwinding library - I have implemented scope(failure) and scope(success) features in C++.
It is based on platform specific function uncaught_exception_count. It is similar to std::uncaught_exception from standard library, but instead of boolean result it returns unsigned int showing current count of uncaught exceptions.
Currently it is tested on {Clang 3.2, GCC 3.4.6, GCC 4.1.2, GCC 4.4.6, GCC 4.4.7, MSVC2005SP1, MSVC2008SP1, MSVC2010SP1, MSVC2012} x {x32, x64}.
In C++11 folowing syntax is available:
try
{
int some_var=1;
cout << "Case #1: stack unwinding" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
throw 1;
} catch(int){}
{
int some_var=1;
cout << "Case #2: normal exit" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
}
In C++98 it is a bit more noisier:
try
{
cout << "Case #1: stack unwinding" << endl;
BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END
SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END
throw 1;
} catch(int){}
{
cout << "Case #2: normal exit" << endl;
BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END
SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END
}
Also, library has UNWINDING_AWARE_DESTRUCTOR feature. Example:
struct DestructorInClass
{
UNWINDING_AWARE_DESTRUCTOR(DestructorInClass,unwinding)
{
cout << "DestructorInClass, unwinding: "
<< ( unwinding ? "true" : "false" ) << endl;
}
};
However, there are some cases where UNWINDING_AWARE_DESTRUCTOR may give wrong results (though scope(success) and scope(failure) features are not affected by such issues).
Related
In question about scope of exception it is stated by Aj. that throw and catch clauses will create copies of the exception (unless reference is used I guess)
I tried myself a small toy code and I don't understand the result. here :
//g++ 7.4.0
#include <iostream>
using namespace std;
struct Some_error {
Some_error(float code):err_code(code){ cout << "Some_error(" << err_code << ")\n"; }
~Some_error() { cout << "~Some_error(" << err_code << ")\n"; }
Some_error(const Some_error& o):err_code(o.err_code+0.1) { cout << "Some_error(copy::" << err_code << ")\n"; }
Some_error(Some_error&& o):err_code(std::move(o.err_code)+.01){ cout << "Some_error(move::" << err_code << ")\n"; }
int get_code() const { return err_code; }
private : float err_code;
};
int do_task() {
if ( false ) return 42; else throw Some_error {1};
cout << "end do_task\n" ;
}
void taskmaster(){
try { auto result = do_task(); cout << "the answer is " << result << "\n" ; }
catch (Some_error e) { cout << "catch Some_error : " << e.get_code() << "\n" ; }
cout << "end taskmaster\n" ;
}
int main() { taskmaster(); }
the trace I get is as follows :
Some_error(1)
Some_error(copy::1.1)
catch Some_error : 1
~Some_error(1.1)
~Some_error(1)
end taskmaster
Now first, as I used no reference here, according to Aj., I would expect 2 copies to happen.
And second, there was a copy, that set err_code to 1.1, but the display is still 1.
Remark: just to be complete, I changed the catch to : catch(Some_error& e),
and then the trace looks fine to me :
Some_error(1)
catch Some_error : 1
~Some_error(1)
end taskmaster
I would expect 2 copies to happen.
Why? Only one copy is made by the catch block. Where would the second copy happen?
set err_code to 1.1, but the display is still 1.
Because get_code returns an int, so the floating point value gets truncated.
I have the following code:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A::A()" << endl;}
~A() { cout << "A::~A()" << endl; throw "A::exception";}
};
class B {
public:
B() { cout << "B::B()" << endl; throw "B::exception";}
~B() { cout << "B::~B()";}
};
int main() {
try {
cout << "Entering try...catch block" << endl;
A objectA;
B objectB;
cout << "Exiting try...catch block" << endl;
} catch (char const * ex) {
cout << ex << endl;
}
return 0;
}
Now, before stating the question, I would like to point that this code is bad practice (e.g throwing an exception from a constructor will result the object not being fully created, thus the destructor won't be called and it might cause memory leaks or other problems).
Now, The order of the main is this:
Printing "Entering try...catch block".
Calling A's constructor, printing "A::A()"
Calling B's constructor, printing "B::B()", and throws exception.
The exception was thrown, and the line "Exiting try...catch block" will not be printed. The block is exited, so A's destructor is called.
A's destructor prints "A::~A()" and throws another exception.
The second exception (in 5) causes the main to throw an exception, before entering the catch block.
My question is this - is there a way to catch the second exception in the main, without altering the classes A,B?
I have tried to surround both the whole try-catch block and inside the catch block with another try-catch block but that didn't work.
Thanks.
From cppreference.com:
As any other function, a destructor may terminate by throwing an exception [...] however if this destructor happens to be called during stack unwinding, std::terminate is called instead.
So, the attempt to throw an exception from ~A() does not result in a second exception being thrown; it results in the program being terminated. If you need to "catch" this "second exception", you would need to interfere with the termination handler. Or you could find a way to not throw an exception in the destructor. Continuing from cppreference.com:
Although std::uncaught_exception may sometimes be used to detect stack unwinding in progress, it is generally considered bad practice to allow any destructor to terminate by throwing an exception.
You may use set_terminate+longjmp in order to avoid program termination.
#include <iostream>
#include <setjmp.h>
using namespace std;
jmp_buf jmpBuf;
class A {
public:
A() { cout << "A::A()" << endl;}
~A() noexcept(false){ cout << "A::~A()" << endl; throw "A::exception";}
};
class B {
public:
B() { cout << "B::B()" << endl; throw "B::exception";}
~B() { cout << "B::~B()";}
};
int main() {
set_terminate([](){
cout<<"long jump begin" << endl;
longjmp(jmpBuf,1);
});
if(setjmp(jmpBuf)==0) {
try {
cout << "Entering try...catch block" << endl;
A objectA;
B objectB;
cout << "Exiting try...catch block" << endl;
} catch (char const *ex) {
cout << ex << endl;
}
}else{
cout<<"long jump end" << endl;
}
return 0;
}
I'd like to write a function for logging which should be used like this:
log(__FILE__) << "My message containing integer: " << 123 << " and double: " << 1.2;
This should print the following line, add endl and flush immediately:
main.cpp: My message containing integer: 123 and double: 1.2
My (simplified) attempt for the implementation of the function:
class Writer
{
public:
template<typename T>
Writer & operator<<(T t)
{
cout << t << endl;
cout.flush();
return (*this);
}
};
Writer log(const char* fileName)
{
cout << fileName << ": ";
return Writer();
}
int main(int argc, const char *argv[])
{
log(__FILE__) << "My message containing integer: " << 123 << "and double: " << 1.2;
return 0;
}
My problem is that because of L-R associativity of the operator<< the output is:
main.cpp: My message containing integer:
123
and double:
1.2
Is there any way how to implement the function or is my requirement for its usage unrealizable?
Ideally I'd like to use plain C++03 (i.e. no C++11 features, boost and non-standard libraries).
L-R associativity is not related to your problem (if you talk about line breaks). The problem is because you use endl after each write. You don't need it (and if you do that, then you don't need flush, because endl already flushes the output).
The easy solution to your problem:
class Writer
{
public:
template<typename T>
Writer & operator<<(T t)
{
cout << t;
return (*this);
}
~Writer()
{
try {
cout << endl;
}
catch (...) {
// You have to make sure that no
// exception leaves destructor
}
}
};
It is also worth to notice, that your approach is not really scalable: it is impossible to use your code in multi-threaded environment. Assume that two threads are writing into your logging:
Thread 1: log(__FILE__) << "a" << "b" << "c";
Thread 2: log(__FILE__) << "a" << "b" << "c";
Here you can easily get a message "aabbcc\n\n" in your logfile, which is highly undesirable.
In order to avoid that, you can have a static mutex object inside log() function, which you pass into Writer constructor. Then you have to lock it in the constructor and unlock it in the destructor. It will guarantee the synchronization of concurrent writing of different entries.
I want to know how to apply exception handling when the top variable reaches to a value -1 (no element left to pop). Currently, I am using cout to nofity the user about the stack underflow and returning 0, which is not a good practice. What improvement overall can be made to this pop function and how to notify user and handle the exception when stack reaches a state of underflow.
int Mystack::pop()
{
if (isEmpty())
{
std::cout << "Stack Underflow" << std::endl;
}
else
{
std::cout << "The popped element is" << A[top];
return A[top--];
}
return 0;
}
The Main Section :
case 4:
std::cout << "POP the element" << std::endl;
s1.pop();
break;
You can throw an out_of_range exception:
#include <stdexcept>
int Mystack::pop()
{
if (isEmpty())
throw std::out_of_range("Stack Underflow");
std::cout << "The popped element is" << A[top];
return A[top--];
}
On the client side:
void foo()
{
Mystack ms;
//...
try
{
ms.pop();
}
catch (const std::out_of_range& oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
}
Edit: As the comments below mentioned, you can also derive your own exception from std::exception. Here is a simple example:
#include <stdexcept>
struct myStackException : public std::exception
{
const char *what() const noexcept { return "Stack Overflow"; }
};
int Mystack::pop()
{
if (isEmpty())
throw myStackException();
std::cout << "The popped element is" << A[top];
return A[top--];
}
Live (dummy) example: http://ideone.com/ZyqiQ0
Re
” What improvement overall can be made to this pop function
You can
Make it void to make it more exception safe for other item types.
With the current design, if copying of the popped item fails, then there is no way to recover.
Remove internal output.
assert that the underflow doesn't occur, so that this can be caught in testing.
Thus,
void Mystack::pop()
{
assert( top > 0 );
--top;
}
Wow, what a simplification – and now more exception safe too!
As an alternative to the assert you can throw an exception. That's better than the original, but absolutely not better than the assert. It moves correctness issues into the runtime domain, to be handled and perhaps worked around by each caller site.
The benefit of using C++ exceptions is that error handling code can be separated from user code, alleviating the need for code to be littered with error handling code that is common in C programs. Throwing an exception also offers a solution to returning a invalid value in the error case
if( s1.pop() == 0 ){
// is this an error or not?
}
Exceptions can be added to your code like so, by taking advantage in the generic exceptions in the
#include <stdexcept>
header file.
int Mystack::pop()
{
if (isEmpty())
{
throw std::range_error("nothing to pop");
}
std::cout << "The popped element is" << A[top];
return A[top--];
}
Then you add a try/catch block to the appropriate code, perhaps with
case 4:
std::cout << "POP the element" << std::endl;
try{
s1.pop();
}
catch(const std::range_error& e)
{
std::cerr << "unable to pop!\n";
// error handling code
}
break;
Another solution, particularly appropriate when errors aren't as exceptional, such as with file I/O is more intrusive to the user code, but offers a better solution than returning an arbitrary value
int Mystack::pop(int& value)
{
if( isEmpty() )
{
return 1;
}
std::cout << "The popped element is" << A[top];
value = A[top--];
return 0
}
And then your code becomes
case 4:
std::cout << "POP the element" << std::endl;
{
int value;
if( s1.pop(value) == 1 ){
// error code
}
}
break;
I'm just learning how to use exceptions in C++ and have come across weird behavior in my "test" code. (excuse overly stupid questions like this one, please...it's NOT lack of research/effort, just lack of experience!) If I'm catching just the exception DivideByZero it works fine.
But introducing the second exception StupidQuestion makes the code not work exactly how I expected. How I wrote it below I thought it should take care of the DivideByZero exception if it needs to, and if not then check if StupidQuestion occurs, and if not just go back to the try clause and print the normal result. But if I input, say, a=3 and b=1, the program redirects to the DivideByZero try clause instead of the StupidQuestion one. The weird thing is, though, divide does seem to be throwing StupidQuestion (see via cout statement), but it's not catching right, as also seen by the absense of the cout statement.
#include <iostream>
#include <cstdlib>
using namespace std;
const int DivideByZero = 42;
const int StupidQuestion=1337;
float divide (int,int);
main(){
int a,b;
float c;
cout << "Enter numerator: ";
cin >> a;
cout << "Enter denominator: ";
cin >> b;
try{
c = divide(a,b);
cout << "The answer is " << c << endl;
}
catch(int DivideByZero){
cout << "ERROR: Divide by zero!" << endl;
}
catch(int StupidQuestion){
cout << "But doesn't come over here...?" << endl;
cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}
system("PAUSE");
}
float divide(int a, int b){
if(b==0){
throw DivideByZero;
}
else if(b==1){
cout << "It goes correctly here...?" << endl;
throw StupidQuestion;
}
else return (float)a/b;
}
I was wondering if it had something to do with the fact that DivideByZero and StupidQuestion were both of type int, so I changed the code to make StupidQuestion be of type char instead of int. (So: const char StupidQuestion='F'; and catch(char StupidQuestion) were really the only things changed from above) And it worked fine.
Why isn't the above code working when the two exceptions have the same type (int)?
Instead of this
catch(int DivideByZero) {
cout << "ERROR: Divide by zero!" << endl;
}
catch(int StupidQuestion) {
cout << "But doesn't come over here...?" << endl;
cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}
you are looking for
catch (int errval) {
if (errval == DivideByZero) {
cout << "ERROR: Divide by zero!" << endl;
}
else if (errval == StupidQuestion) {
cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}
else {
throw; // for other errors, keep searching for a handler
}
}
The variable name inside the catch clause is creating a new local variable, which has no relation to a global constant with the same name.
Also note that there will be no way to catch just one error number... but you can rethrow unknown errors as I show.
catch(int DivideByZero) { }
catch(int StupidQuestion) { }
Both catch blocks catch ints, they're just named differently. Only the first one can ever be entered, the second one is dead code.
When choosing a handler for an exception only type is taken into account, and neither values nor addresses (addresses of variables are not applicable here at all because of how exceptions work), also names of variables do not exist after compilation.
The first appropriate handler for the exception is always chosen.
Please look my answer to another question for details: https://stackoverflow.com/a/45436594/1790694