Qt error handling for fortran subroutines - c++

I have a Qt GUI project that calls a fortran subroutine from a C++ function. This fortran subroutine reads some data from a text file. But whenever the fortran code fails (e.g. bad integer in item list etc), the GUI window automatically closes.
Is there a way to prevent it from closing if an error occures?
I tried using try-catch blocks like this
try
{
// fortran function call
test_();
}
catch(...)
{
qDebug()<<"Error";
}
but it didn't work. Throwing exceptions with the throw statement does work however.
I also tried to subclass QApplication class and reimplement the notify() function:
bool SafeApp::notify(QObject* obj,QEvent* event)
{
try
{
return QApplication::notify(obj,event);
}
catch(std::exception& e)
{
return false;
}
}
The code compiles and runs fine, but it still crashes after calling the fortran function.

Fortran does not have exceptions, so the Fortran function you're calling is not throwing anything that C++ can catch.
OTOH, in Fortran the default behavior for errors such as I/O errors is to stop the program. The GFortran runtime library uses the libc exit() or abort() functions for this, depending on what kind of error is encountered.
What you might be able to do, is to add IOSTAT= and/or IOMSG= specifiers to the Fortran I/O statements. In that case errors will cause a nonzero iostat and some message in the string pointed to by IOMSG rather than stopping the program.

Related

Catching fortran runtime errors and signals in C++ binding

I would like to be able to catch a terminating Fortran runtime errors in a C++ binding.
I have a legacy F90 code to bind to and expect all kind of errors e.g. numerical, IO etc.
I managed to handle STOP according to:
Intercepting Fortran STOP from C++
and able to throw/catch exception for this case in the C++ code.
I got some understanding 'Signal Handling in Fortran' at
https://www.sharcnet.ca/help/images/4/42/Fortran_Signal_Handling.pdf
However I do not manage with this, an example for f90 fortran would be very helpful.
For example trying to open a non existant file in the fortran subroutine would give a runtime error, and the C++ code terminates:
open (unit=13,FILE="fnameBAD",status="old",action="read",position="rewind")
Fortran runtime error: Cannot open file 'fnameBAD': No such file or directory
I would like to be able to catch this and other runtime errors using signals.
This won't work, at least for GFortran. When then OPEN statement fails, the GFortran runtime library will shut itself down, and only finally is the signal generated. So by the time you can catch the signal in the signal handler, libgfortran has already shut itself down (including closing all open files).
The solution, as Vladimir F says in a comment, is to catch the error in the OPEN statement with the iostat= specifier.
I've implemented something like that for unittesting C-bindings for a Fortran code from C/C++ to catch abort calls using setjmp and longjmp (essentially the same as an answer in the already linked question):
#include <setjmp.h>
#include <signal.h>
jmp_buf jmp_env;
void on_sigabrt(int signum)
{
(void) signum; // silence "unused parameter" warning
longjmp(jmp_env, 1);
}
void func()
{
if (setjmp(jmp_env) == 0) {
signal(SIGABRT, &on_sigabrt);
/* YOUR CALLS HERE */
} else {
/* ERROR HANDLING GOES HERE */
}
}
The problem #janneb already described remains: Even while longjmp should restore the stack to the point of the setjmp, it does not guarantee that all internal state in the Fortran runtime library is restored.
In fact, both books Modern Fortran: Style and Usage (rule 182) and The Fortran 2003 Handbook (15.6.4) mention that Fortran code should not be wrapped in between setjmp and longjmp.
On the other hand, there are compiler vendors which explicitly provide setjmp/longjmp wrappers (Oracle for example), as well as several projects with a similar focus:
funwind
zsvjmp
That being said, it is likely a better (and more portable) approach to use proper error handling using the iostat attribute whenever possible, as others already commented.

Catch exceptions for C++ function I called in Objective-C?

My iPad app is using Objective-C for UI, and it calls some C++ functions for computation. Since the C++ code is not well written, it sometimes throw exceptions or causes segmentation fault when tested alone. However, the C++ code is currently under development by someone else so I don't want to change it. Is it possible to catch the exceptions and segmentation fault in my Objective-C code so that I don't need to change the C++ code? I tried the basic try-catch, but it seems not working. (wrapper is the buggy c++ function)
#try {
wrapper([imageName UTF8String]);
}
#catch (NSException *e) {
NSLog(#"Error");
}
When I run my app and click the button that calls C++ functions, the simulation crashes and an error message says libc++abi.dylib: terminating with uncaught exception of type NSException
you can use C++ try-catch with Objective-C++ code (.mm extension)
try {
wrapper([imageName UTF8String]);
}
catch (...) {
NSLog(#"Error");
}
In 64-bit processes, you can use #catch(...) to catch everything including C++ exception
#try {
wrapper([imageName UTF8String]);
}
#catch (...) {
NSLog(#"Error");
}
Your can write cpp code in your file (.mm extension instead of .m) and use a C++ try/catch like this:
#include <stdexcept>
try
{
wrapper([imageName UTF8String]);
}
catch (const std::exception & e)
{
NSLog(#"Error");
}
I am not sure if this is what you are looking for, but maybe that helps too.
You can add exception breakpoint if you debug your app with Xcode.
Go to Breakpoint Navigator, find the little "+" sign at the bottom, click and choose Add Exception Breakpoint. From now when your app throws an exception, Xcode shows you which line throws it. By default Breakpoint Exception works for Objective-C and C++ exceptions, you can change that by right-clicking the exception in Breakpoint Navigator.
Your code as written should catch NSExceptions thrown by the C++ code as long as all of the code in the stack trace between the throw and the catch is compiled with exceptions enabled. Check your compiler flags.
You cannot catch segmentation faults with an exception handler. It is not impossible to catch them with a signal handler, but it's generally impossible to do anything useful to recover so we don't recommend it.

Trying to catch exception in MFC's CString::Format

I am working with a C++ project (that I was not the author of) that has a lot of MFC string formatting functions. Unfortunately, stuff like %d and %s are very close together (including the location of letters d and s on the keyboard) that one can be transposed with another. So I may at times witness a code line as such:
CString s;
s.Format(L"Value v=%s", 100); //Should've been %d instead
This results in a hard crash of the process, that is very hard to locate & isolate in the final project. So I was thinking to wrap the Format function in my own override and catch the exception & log it before it is thrown as unhandled exception.
So I employed the following construct:
__try
{
//Do the Format function here
}
__except(1)
{
//Log the error, etc.
}
But unfortunately the construct above did not catch the exception from the first code chunk, so I got VS 2008 C++ debugger kick in and show this:
I then tried this:
try
{
//Do the Format function here
}
catch(int e)
{
//Do the logging
}
But that didn't catch it either.
So how can I catch that fault?
PS. And I have a second question. Is there an easy way to override an MFC function, like Format for instance?
MFC throws CException pointers, so you could try this:
try
{
// Do the Format function here
}
catch(CException* e)
{
// Do the logging then free the exception
if (m_bThrowExceptionAgain)
throw; // Do not delete e
else
e->Delete();
}
You have to delete the exception object once you have caught it as shown in the example. Also make sure you have C++ exceptions enabled in your compiler. See http://msdn.microsoft.com/en-us/library/0e5twxsh.aspx for more information.
As others have already said low-level exceptions (like access violations) are not the same as C++ exceptions. They fall under the term Structured Exception Handling and would require other means to catch, at least by default.
It's possible to change compiler settings (at least in Visual Studio) to make it wrap those exceptions into something that C++ try/catch statements can handle, but as I recall that loses the details of what the SEH exception was and where it came from.
One way or another you could probably get exceptions to work well enough to help track down these issues, but there is also another way: Use static code analysis.
While standard C++ compilers don't normally verify format/printf-style calls, there are various tools that will. In fact some recent versions/editions of Visual Studio come with a code analysis tool, although it may not have been available in VS 2008 which you mentioned. So it might be worthwhile for you to do some research and see if you can get a hold of some kind of code analysis tool which could then catch all the CString::Format mistakes during analysis/compile-time rather than run-time.
You can use _set_se_translator() to convert SEH exceptions like access violation to C++ exceptions which you can then catch with except().
Some sample code: http://www.codeproject.com/Articles/422/SEH-and-C-Exceptions-catch-all-in-one

Exception is not caught although it is included in catch statement

I have this program written in C++ Builder 6. I didn't write all the code, just some of it. The language, however, is not C++ (as far as I'm aware) - it looks more like Delphi or Pascal. So that's why I included them all in the tags.
I have an int called Oversteering.
try
{
Oversteering=HoursCounter.ToInt();
}
catch(EConvertError &convertError)
{
Oversteering=0;
}
HoursCounter is an AnsiString, and it is in the form of an int.
Since this is the only try/catch statement in the whole code (that's not too good, I know), and I couldn't find any good example of such in Delphi/Pascal/???, I don't know if it's correctly written.
Well, I try to convert the string to an int. Sometimes I get this error:
That is, an exception called EConvertError has occurred.
So my question is: why is this exception NOT caught by the catch statement?
This error is shown by the debugger when running through the code,
if you run the exe and have the same situation the error message will not be shown to you
The exception is caught but the debugger is notifiying you regarding the error in the code
that is here
try
{
Oversteering=HoursCounter.ToInt();
}
since running in the debugger the ,your trying to convert (blankspace) '' to integer, the debugger will show the exception...but when running the exe, the debugger will set
Oversteering=0
check this from about.com
Break On Exceptions
When building a program with exception handling, you may not want Delphi to break on Exceptions. This is a great feature if you want Delphi to show where an exception has occurred; however, it can be annoying when you test your own exception handling.
As #PresleyDias explained, it is the debugger that is displaying the exception, not your app. The exception is being caught (you should be catching it by a const reference, though), but the debugger sees it before your app does, that's all. You can configure the debugger to ignore EConvertError, if you like.
A better solution is to avoid the exception in the first place. If you use AnsiString::ToIntDef() instead, you can remove the try/catch block completely:
Oversteering = HoursCounter.ToIntDef(0);
Alternatively, you can use TryStrToInt() instead:
if (!TryStrToInt(HoursCounter, Oversteering))
{
...;
}
If 0 is a valid value for your counter, use TryStrToInt():
if (TryStrToInt(HoursCounter, Oversteering))
{
// use Oversteering as needed, even zeros...
}
else
ShowMessage("Cannot convert HoursCounter to a valid integer!");
If 0 always represents an error, then use ToIntDef():
Oversteering = HoursCounter.ToIntDef(0);
if (Oversteering != 0)
{
// use Oversteering as needed, except zeros...
}
else
ShowMessage("Cannot convert HoursCounter to an acceptable integer!");

Handling C++ exception thrown in function exported to QtScript

I am using the Qt script engine in my application as an alternative way for the user to access its functionality. As such, I export some C++ classes to the Qt ScriptEngine, that will serve as the interface to the application. The problem is, these C++ classes can throw exceptions.
I have a "ScriptInterface" class running on its own thread, listening for requests to process scripts. So when I evaluate a user's script, I have a try/catch block around it to handle exceptions, and print the error to the console in the application.
...
try {
m_engine->evaluate(script, name);
}
catch (Exception const& e) {
// deal with it
}
catch (...) {
// scary message
}
This works perfectly in windows... but doesn't work in linux- the program terminates with this message:
terminate called after throwing an instance of 'Basilisk::InvalidArgumentException'
what(): N8Basilisk24InvalidArgumentExceptionE
Aborted
I had a hunch that it was because the exceptions bubbled up to the event handler (since the script engine uses signals to call the functions in my exported classes), so I reimplemented QApplication::notify, to handle exceptions there, but they weren't caught.
My question is, am I doing something fundamentally wrong? Also, as an alternative, is it possible to explicitly throw script exceptions from within my C++ classes?
Thanks in advance
EDIT: fixed the description to include the catch(...) statement.
UPDATE (SOLUTION): I "fixed" this problem by following a strategy similar to the one outlined in the accepted answer. Although I haven't gone to the source of why the exceptions don't get caught on linux (my suspicion now, is that m_engine->evaluate spawn a seperate thread on linux), but I have started using the intended way of exception throwing in Qt Scripts, and that is QScriptContext::throwError().
In cases where my function would look like this: (random example)
void SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
throw InvalidArgumentException(
"Not the answer to Life, the Universe and Everything.");
}
// function that is not part of the scripting environment,
// and can throw a C++ exception
dangerousFunction(argument);
}
It is now this: (pay particular attention to the return type)
QScriptValue SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
// assuming m_engine points to an instance of
// QScriptEngine that will be calling this function
return m_engine->currentContext()->throwError(QScriptContext::SyntaxError,
"Not the answer to Life, the Universe and Everything.");
}
try {
// function that is not part of the scripting environment,
// and can throw a C++ exception
dangerousFunction(argument);
} catch (ExpectedException const& e) {
return m_engine->currentContext()->throwError(QScriptContext::UnknownError,
e.message());
}
// if no errors returned, return an invalid QScriptValue,
// equivalent to void
return QScriptValue();
}
So where does one deal with these script errors? After the call to QScriptEngine::evaluate() you can check whether there are any uncaught exceptions, with QScriptEngine::hasUncaughtException(), obtain the error object with uncaughtException(), and now you have the message, the trace, and line number in the script where the error occured!
Hope this helps someone out!
I ran into a similar type of problem when trying to use SWIG with Python to wrap C++ libraries. Eventually what happened was that I made a stub for all the wrapped classes which caught the exception and failed quietly. Luckily I had the luxury of wrapping functionality which only passed container classes and state pattern objects, so I could easily check if something was amiss. May I suggest the same for you?
Wrap the functions you want with another function, same interface except the return value.
Create an object that contains not only the requested return type but also an error indicator.
Have the script make sure to check for the exceptions.
And yes, it's very possible for a script engine to throw C++ exceptions if you've given it access to an exception factory (a class whose sole purpose is to throw C++ exceptions.)
Run your program under a debugger and place a breakpoint inside your runtime library's terminate() function. That way you'll stop on terminate() in the debugger and by inspecting the call stack you will then see from where terminate() was called.