I have a function that may throw an exception of a variable type, but all inheriting from std::exception:
int errorCheck(int a)
{
if(a < 0)
throw a_too_small();
if(a>10)
throw a_too_big();
return a*2;
}
I want to handle this exception using Qt's SIGNAL/SLOT mechanism.
try {
errorCheck(a);
} catch(std::exception &e) {
emit errorSignal(e);
}
If the signature of errorSignal is errorSignal(std::exception e), then the original exception object is sliced and its type is lost.
If the signature is errorSignal(std::exception &e) on the other hand, the exception e leaves the catch scope, and I believe this is not allowed.
What's the cleanest solution to handle this problem?
If using C++11 is possible, you can try to use std::exception_ptr:
try {
...
} catch (...)
std::exception_ptr except = std::current_exception();
emit signal(except);
}
Then in your slot:
void myslot(std::exception_ptr e) {
try {
if (e) {
std::rethrow_exception(e);
}
} catch (...) {
...
}
}
How about making the errorSignal function signal/slot work by reference? something like errorSignal(std::exception& e)? Do that with Qt::DirectConnection too to avoid event queuing, with something like:
connect(someWidget,SomeWidget::errorSignal&,this,MainWindow::handleError&,Qt::DirectConnection);
Related
I know that you can catch "all exceptions" and print the exception by
try
{
//some code...
}catch(const std::exception& e) {
cout << e.what();
}
but this is just for exceptions derived from std::exception.
I was wondering if there is a way to get some information from an ellipsis catch
try
{
//some code...
}catch(...) {
// ??
}
If the mechanism is the same as ellipsis for functions then I should be able to do something like casting the argument of the va_list and trying to call the what() method.
I haven't tried it yet but if someone knows the way I'd be excited to know how.
From C++11 and onwards, you can use std::current_exception &c:
std::exception_ptr p;
try {
} catch(...) {
p = std::current_exception();
}
You can then "inspect" p by taking casts &c.
In earlier standards there is no portable way of inspecting the exception at a catch(...) site.
Sorry, you can't do that. You can only access the exception object in a catch block for a specific exception type.
I have following function that catches the system-exception of a ComObject and throws my own exception off:
int TReader::ExecSQL(...) {
try {
// ...
} catch (Comobj::EOleException& e) {
throw myDBError("TReader::Open", "TReader", e.Message);
}
// ...
}
I can not catch my own exception, getting always "Exception unknown!"! Why?
void main() {
try {
ExecSQL(...);
} catch(myDBError& e) {
log(e.Message);
} catch(...) {
log("Exception unknown!");
}
}
Use catch(const myDBError& e) { instead.
An anonymous temporary cannot bind to a non-const reference, so a throw will not be intercepted at the current catch site.
If try-catch block generates not Comobj::EOleException, but something else, that may be problem.
Also check, maybe myDBError constructor generates another exception, with another type :-)
That would be funniest explanation, why you can't catch myDBError, but still catch something :-)
I am using QT 4.8 (C++) for desktop application project, and writing exception handling which is as follows :
void callerMethod()
{
try
{
method1();
}
catch(Exception1& e)
{
// display critcal error message
// abort application
}
catch(std::Exception& e)
{
// print exception error message
}
catch(...)
{
// print unknown exception message
}
}
void method1()
{
try
{
// some initializations
// some operations (here exceptions can occur)
// clean-up code (for successful operation i.e no exception occurred)
}
catch(Exception1& e)
{
// clean-up code
throw e;
}
catch(Exception2& e)
{
// clean-up code
throw e;
}
catch(Exception3& e)
{
// clean-up code
throw e;
}
catch(...)
{
// clean-up code
throw;
}
}
So my question do I need to write the clean-up code in every catch block?
Is there any way I can avoid writing repeated code?
NOTE:: [ In method1() ] I want to re-throw exceptions which occurred
to my caller.So I can not catch them in single catch block,
because then type information will be lost.
Method1 can be much simplified by two concepts:
RAII. Put any clean-up code into destructors, and the clean-up code will be centralized.
Use the unqualified throw, and you won't need to know about the type of exception thrown.
So, method1() should look like:
void method1()
{
// some initializations of RAII objects
// some operations (here exceptions can occur)
}
The first catch clause in callerMethod can be removed if you derive Exception1 from std::exception, since the what() method is virtual.
You should throw exceptions as low as possible and catch them as high as possible in the call chain. This automatically leads to less code duplication, and centralizes error handling. You are throwing/catching all in one place, which seems a bit ... forced.
I often do this kind of thing (especially for program-ending exceptions:
int main()
try
{
function_calls_that_may_throw();
// ...
}
catch(my_exception& e)
{
e.do_exception_stuff();
}
catch(std::exception& e)
{
std::cout << e.what();
}
catch(...)
{
std::cout << "Something bad happened.\n";
}
This is only possible for throwing exceptions you don't plan on handling better or retrying the failed operation or something.
The pro of this approach is that all/most error handling code is at the top-level of your program, and all the functions in the call chain don't have to worry one bit about this stuff, all they do is throw an exception when they feel like it.
If all your clean up code is totally identical, you can do everything in your catch (...) block:
try {
// code
} catch (...) {
// cleanup
throw;
}
If your code varies slightly, you can always call a cleanup function:
try {
// code
} catch (exc1 ex) {
cleanup(args);
// exc1 specific
throw;
} catch (exc2 ex) {
cleanup(args);
// exc2 specific
throw;
} catch (...) {
cleanup(args);
throw;
}
Consider the following C++ code:
try {
throw foo(1);
} catch (foo &err) {
throw bar(2);
} catch (bar &err) {
// Will throw of bar(2) be caught here?
}
I would expect the answer is no since it is not inside the try block and I see in another question the answer is no for Java, but want to confirm C++ is also no. Yes, I can run a test program, but I'd like to know the language definition of the behavior in the remote case that my compiler has a bug.
No. Only exceptions thrown in the associated try block may be caught by a catch block.
No, It won't, An enclosing catch block upwards the hierarchy will be able to catch it.
Sample Example:
void doSomething()
{
try
{
throw foo(1);
}
catch (foo &err)
{
throw bar(2);
}
catch (bar &err)
{
// Will throw of bar(2) be caught here?
// NO It cannot & wont
}
}
int main()
{
try
{
doSomething();
}
catch(...)
{
//Catches the throw from catch handler in doSomething()
}
return 0;
}
No, a catch block handles the nearest exception, so if you try ... catch ( Exception &exc ) ... catch ( SomethingDerived &derivedExc ) the exception will be handled in the &exc block
You might achieve the desired behaviour by exception delegation to the calling method
Which one should I use?
catch (_com_error e)
or
catch (_com_error& e)
The second. Here is my attempt at quoting Sutter
"Throw by value, catch by reference"
Learn to catch properly: Throw exceptions by value (not pointer) and
catch them by reference (usually to const). This is the combination
that meshes best with exception semantics. When rethrowing the same
exception, prefer just throw; to throw e;.
Here's the full Item 73. Throw by value, catch by reference.
The reason to avoid catching exceptions by value is that it implicitly makes a copy of the exception. If the exception is of a subclass, then information about it will be lost.
try { throw MyException ("error") }
catch (Exception e) {
/* Implies: Exception e (MyException ("error")) */
/* e is an instance of Exception, but not MyException */
}
Catching by reference avoids this issue by not copying the exception.
try { throw MyException ("error") }
catch (Exception& e) {
/* Implies: Exception &e = MyException ("error"); */
/* e is an instance of MyException */
}
Personally, I would go for the third option:
catch (const _com_error& e)
Also, note that, when using MFC, you may have to catch by pointer. Otherwise, #JaredPar's answer is the way you should normally go (and hopefully never have to deal with things that throw a pointer).
Definitely the second. If you had the following:
class my_exception : public exception
{
int my_exception_data;
};
void foo()
{
throw my_exception;
}
void bar()
{
try
{
foo();
}
catch (exception e)
{
// e is "sliced off" - you lose the "my_exception-ness" of the exception object
}
}