Exceptions Handling

Exceptions Handling

Dear all,

I'm currently rewritting an old FORTRAN program, and I would like to have a clean exception handling, such as the try {} catch {} in C++.

Using my own exceptions, I would be able to generate specific exceptions, such as non-convergence in a mathematical model, and to catch it at a higher level so as to continue program execution.

Is there any feature in Intel Fortran Compiler that could help me ? Or is it possible to emulate something ? I have access to IFC version 13.1, and maybe to version 14, and also to C/C++ compilers.

Thank you.

11 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Fortran is somewhat limited in terms of native capabilities in structured exception handling compared to C++, etc.  See an article by Arjen Markus at ACM SIGPLAN Fortran Forum on some ideas on what one can do using Fortran.

Also, Fortran does have the various IEEE_xxx intrinsic modules that give you some control/visibility into arithmetic operations, but probably not what Felix is looking for.

Steve - Intel Developer Support

Thank you FortranFan for the paper, I had a look at it but the exception management A. Markus proposes uses alternate returns, which are obsolete in F2003.

I plan also to use the IEEE modules, but this feature is limited to floating point exceptions.

Do you know if one can throw C++ exceptions from Fortran code, and catch it at a higher level ? Maybe by wrapping the whole code in C++ ? By the way, does anyone knows why Fortran does not provides exceptions ?

Thanks,

Felix

Quote:

felix.arnoux wrote:

Thank you FortranFan for the paper, I had a look at it but the exception management A. Markus proposes uses alternate returns, which are obsolete in F2003.

I agree and that's one of the things I meant by limitations in Fortran, but I wasn't explicit since I figured it'll be better if you reviewed the paper yourself.

Quote:

felix.arnoux wrote:

Do you know if one can throw C++ exceptions from Fortran code, and catch it at a higher level ? Maybe by wrapping the whole code in C++ ?

Note my experience is on Windows platform and I use Microsoft's .NET runtime with Visual C++ and C#.  But I would think the concept should be generally valid everywhere.  So the thing I do in one of my applications is have a callback mechanism from my Fortran library to a custom exception handler section in the caller; the caller may be a Fortran or C++ or C#.  In the case of C++ and C#, the custom handler "throws" the conventional exception which then gets handled by try, catch, finally statements that are wrapped around the Fortran calls.  In the Fortran library, all the internal procedures return integer error codes.  The calling procedures process the integer error code in a SELECT CASE construct and for certain error codes (e.g., bad input), the statements following the CASE invoke the callback mechanism.  With this, I don't see the need to wrap all my Fortran libraries in C++.

Quote:

felix.arnoux wrote:

By the way, does anyone knows why Fortran does not provides exceptions ?

I don't know why, but perhaps it'll make it into Fortran 202X or 203X when hopefully Fortran is made fully interoperable with C++ instead of just with C in the current standard ?!? :-))

 

The idea to add exception handling to Fortran has come up over the years, but it has never gained enough support in order to make it in as a work item for the standard. I see on the J3 site a reference to a discussion in 1995 but I can't find the details.

Don't even dream of full interoperability with C++. Not going to happen.

Yes, you can use C++ to catch exceptions raised from Fortran code, but Fortran doesn't itself have features to raise exceptions. I will note that we added an ESTABLISHQQ library routine that allows you to do some level of processing when an error occurs, but it's not quite what you are looking for.

Steve - Intel Developer Support

Quote:

Steve Lionel (Intel) wrote:

...

Don't even dream of full interoperability with C++. Not going to happen.

...

Steve,

You say this because of some fundamental incompatibility between Fortran and C++ or simply because the effort will be so great that it will never pass the cost-benefit test?

There's too much in the way of implementation-dependent aspects of C++ to try to make things such as classes "interoperate". Also, the Fortran standards committee doesn't have a high opinion of C++ and doesn't think that trying to extend interoperability to C++ has much value. C interoperability solves real problems and is tractable.

Steve - Intel Developer Support

I could imagine that C++ would continue to move fast enough that Fortran couldn't catch up even if the performance aspects could be overcome.  Will C++ a decade from now resemble anything you can predict?

I worked for a while on a project where the software vendor wanted to raise C++ exceptions from Fortran, but they weren't able to accept enough aspects of C++ on Intel architecture (e.g.  they would have required an option to make default int a consistent 64-bit data type between Fortran and C++) to keep the project alive.

I tried to generate layers of C++ and Fortran together. I'm not sure I will be able to do everything I wanted to, I fear the hard part will be passing arguments...

Here is the code, if it can help anyone:

subroutine fortran_subroutine()

  use, intrinsic :: iso_c_binding

  integer :: ios
  real :: a, b, c
  
  print *, 'Entering Fortran subroutine.'
  
  ! Test for FPE signal
  a = 1.0
  b = 0.0
  c = a/b
  print *, a, b, c
  
  ! Test for I/O error
  open (unit = 2, file = 'scores', status='old', iostat=ios)
  if (ios /= 0) call throw_exception('An error occurred while reading file score')
  
  print *, 'Leaving Fortran subroutine.'

end subroutine fortran_subroutine

program test

  use iso_c_binding

  abstract interface
      subroutine sub ()
      end subroutine sub
   end interface

  procedure (sub), pointer :: f_ptr => null ()
  procedure (sub) :: fortran_subroutine

  print *, 'Entering Fortran main program.'

  f_ptr => fortran_subroutine
  status = try_catch_layer(f_ptr)

  print *, 'Leaving Fortran main program, status =', status

end program

And the C++ part:

#include <iostream>
#include <exception>
#include <csignal>


using namespace std;

extern "C" 
{
  void throw_exception_(char * message_from_fortran);
  void try_catch_layer_(void (*pointer_to_fortran_function)(void));
}

// Function that throws an exception with a message
void throw_exception_(char * message_from_fortran)
{
  class my_exception: public exception
  {
    char * my_exception_message;
    virtual const char* what() const throw()
    {
      return my_exception_message;
    }
    public : void set_message(char * message)
    {
      my_exception_message = message;
    }
  } my_ex;

  my_ex.set_message(message_from_fortran);
  throw my_ex;
}

// SignalHandler converts signals (FPE, Ctrl+C, ...) to C++ exceptions
void SignalHandler(int nSig)
{
  switch(nSig)
  {
    case SIGFPE:  
      throw_exception_("Signal SIGFPE was raised.");
      break;
    default:
      throw_exception_("Unhandled signal was raised.");
  }

}

// Intermediate layer of C++ designed to launch a Fortran subroutine
// which doesn't have any argument
void try_catch_layer_(void (*pointer_to_fortran_function)(void))
{
  // Link signals to signal handling function
  signal(SIGFPE,  SignalHandler);
  
  // Run the Fortran function and catch exceptions
  try
  {
    cout << "Entering C++ try_catch_layer." << endl;
    pointer_to_fortran_function();
    cout << "Leaving C++ try_catch_layer." << endl;
  }
  catch(exception& e)
  {
    cout << "An exception occurred: " << e.what() << endl;
  }
}

Compilation was done with Ifort 13 and Icc 13:

icc   -g -traceback -fp-trap=common -c throw_cpp_exception.cpp
ifort -g -traceback -fpe-all=0      -c test.f90
ifort -g -traceback -fpe-all=0 test.o throw_cpp_exception.o -lstdc++ -lifcore -limf

 

RE: if (ios /= 0) call throw_exception('An error occurred while reading file score')

Should the Fortran subroutine be in a nested call of Fortran subroutines, you simply cannot unwind the Fortran call stack using a C++ SEH mechanism. The recent (2003) versions of Fortran have auto-deallocation of local allocatables. This code could be bypassed should the C++ SEH unwind the Fortran stack. For exceptions that terminate the program this will not be an issue. For exceptions that you want to cause a retry, it may cause an issue.

Consider using the alternate return feature of Fortran. This will require more changes to your code, but not much more than the try/catch modifications for a C++ program.

Jim Dempsey

www.quickthreadprogramming.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today