gfortran Catching C++ Exception using iso_c_binding

  • Follow


I am trying to create an example which would allow me to catch an
exception in C++ during a call to a Fortran subroutine. I want to use
this as a crude form of error handling for my program which is mixing C
++ and Fortran using the iso_c_binding module. However, when I try to
do this, it appears that gfortran is handling the exception, rather
than letting it pass back up the stack for C++ to catch. I have
created an example of what I am trying to do and the results for each
case (exceptC.cpp and exceptF.f95).

When I compile and link the files as they are below, I get the
following result:
$ gfortran -c exceptF.f95
$ g++ -o e exceptC.cpp exceptF.o -lgfortran.a
$ ./e

terminate called after throwing an instance of 'std::domain_error'
  what():  Error message because the value 3 is incorrect.
Abort trap

From the above result, it seems that when I throw the domain_error in
the "printstring" method, gfortran is handling the exception before it
can get to the catch I have in main().

To illustrate the difference, I uncomment the lines in exceptC.cpp,
which redefines fortranDriver() as a C++ function, and comment out the
extern "C" fortranDriver() definition below it. Now the code is all C+
+, I am not using gfortran in this case, so the exception is handled
properly:

$ g++ -o e exceptC.cpp
$ ./e

The following error occured: Hello

Is there some flag I can turn off in gfortran to allow the exception
to pass through back to my exception handler? Is what I am trying to
do feasible? I do not quite understand why this is happening.

Thanks,
John N.

Below are the source files:

exceptC.cpp
=============================================================
#include <iostream>
#include <stdexcept>

extern "C" void printstring(char* string_) /* equivalent: char
string[] */
{
    throw std::domain_error(string_);
}

// void fortranDriver()
// {
//     char a[] = "Hello";
//     printstring(a);
// }

extern "C" void fortranDriver();

void driver()
{
    fortranDriver();
}

int main()
{
    try{
        driver();
    }catch(const std::exception& exception_){
        std::cout << "The following error occured: " <<
exception_.what() << std::endl;
    }catch(...){
        std::cout << "An unknown exception occured: " << std::endl;
    }
}
==============================================================

exceptF.f95
==============================================================
module strings
interface
    subroutine printstring(string) bind(C, name="printstring")
    use iso_c_binding, only: c_char
        implicit none
        character(len=1, kind=c_char) :: string
    end subroutine printstring
end interface
end module strings

subroutine fortranDriver() bind(c, name="fortranDriver")
use strings
use iso_c_binding, only: c_char, c_null_char, c_int
implicit none
    character(len=256, kind=c_char) :: a
    integer(c_int) :: b = 3
    write(a,'(a,i0,a)') "Error message because the value ", b, " is
incorrect."
    call printstring(trim(a)//c_null_char)
end subroutine fortranDriver
==============================================================

0
Reply John 10/14/2010 6:48:55 PM

On 10/14/2010 09:11 PM, FX wrote:
>> $ gfortran -c exceptF.f95
>> $ g++ -o e exceptC.cpp exceptF.o -lgfortran.a
> 
> Works for me:
> 
> $ gfortran -c b.f90 ; /usr/local/gfortran/bin/g++ a.cpp b.o -lgfortran -lm  
> $ ./a.out 
> The following error occured: Error message because the value 3 is incorrect.
> 
> 
> gcc version 4.5.1 20100506 (prerelease) (GCC) 
> Target: x86_64-apple-darwin10.3.0
> 

I just tried it with 4.4.1 and 4.5.0, also works.

-- Wolfgang

-- 
E-mail: firstnameinitial.lastname@domain.de
Domain: yahoo
0
Reply Wolfgang 10/14/2010 6:13:00 PM


> $ gfortran -c exceptF.f95
> $ g++ -o e exceptC.cpp exceptF.o -lgfortran.a

Works for me:

$ gfortran -c b.f90 ; /usr/local/gfortran/bin/g++ a.cpp b.o -lgfortran -lm  
$ ./a.out 
The following error occured: Error message because the value 3 is incorrect.


gcc version 4.5.1 20100506 (prerelease) (GCC) 
Target: x86_64-apple-darwin10.3.0

-- 
FX
0
Reply FX 10/14/2010 7:11:30 PM

On 10/14/2010 10:08 PM, John N. wrote:

> Are you by chance using any special configure options to build your
> gfortran? I built mine with the default options from the GFortran Wiki
> (http://gcc.gnu.org/wiki/GFortranSource), as follows:
> 
> $ gfortran -v
> Configured with: ../gcc-4.6-20100925/configure --prefix=$HOME/gcc-trunk
> --enable-languages=fortran --enable-checking=release --disable-bootstrap
> Thread model: posix
> gcc version 4.6.0 20100925 (experimental) (GCC)

The 4.4.1 compiler is the one that comes with the installation:

$ gfortran -v
Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info
--mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64
--enable-languages=c,c++,objc,fortran,obj-c++,java,ada
--enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.4
--enable-ssp --disable-libssp --with-bugurl=http://bugs.opensuse.org/
--with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap
--with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit
--enable-libstdcxx-allocator=new --disable-libstdcxx-pch
--enable-version-specific-runtime-libs --program-suffix=-4.4
--enable-linux-futex --without-system-libunwind --with-arch-32=i586
--with-tune=generic --build=x86_64-suse-linux
Thread model: posix
gcc version 4.4.1 [gcc-4_4-branch revision 150839] (SUSE Linux)

The 4.5.0 one I built with the GFortran Wiki options

$ gfortran45 -v
Using built-in specs.
COLLECT_GCC=gfortran45
COLLECT_LTO_WRAPPER=/home/gcc/install-4.5/libexec/gcc/x86_64-unknown-linux-gnu/4.5.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4_5-branch/configure
--prefix=/home/gcc/install-4.5 --enable-languages=c,c++,fortran
--enable-checking=release --disable-bootstrap
Thread model: posix
gcc version 4.5.0 20100408 (prerelease) (GCC)

I don't use 4.6 versions (yet).

-- Wolfgang


-- 
E-mail: firstnameinitial.lastname@domain.de
Domain: yahoo
0
Reply seesig3208 (122) 10/14/2010 7:20:23 PM

In article <77ea616d-53bc-4724-8ddc-44465b4027a5@t8g2000yqk.googlegroups.com>,
John N. <ortp21@gmail.com> wrote:
>I am trying to create an example which would allow me to catch an
>exception in C++ during a call to a Fortran subroutine. I want to use
>this as a crude form of error handling for my program which is mixing C
>++ and Fortran using the iso_c_binding module. ...

Anyone who needs to ask that on a newsgroup doesn't have a hope in
hell of getting it to work.  Sorry.  Don't bother - you're wasting
your time - think of another way to do it.

If you really intend to proceed, get hold of the source of gcc
(including g++, glibc and gfortran) and investigate what is going
on.  It won't be quick and it won't be easy.

Oh, and watch out for the language issues where making it 'work'
will break features of one or both languages - there are quite a
lot.


Regards,
Nick Maclaren.
-1
Reply nmm1 10/14/2010 7:32:57 PM

On 2010-10-14 13:13:00 -0500, Wolfgang Kilian said:

> On 10/14/2010 09:11 PM, FX wrote:
>>> $ gfortran -c exceptF.f95
>>> $ g++ -o e exceptC.cpp exceptF.o -lgfortran.a
>> 
>> Works for me:
>> 
>> $ gfortran -c b.f90 ; /usr/local/gfortran/bin/g++ a.cpp b.o -lgfortran -lm
>> $ ./a.out
>> The following error occured: Error message because the value 3 is incorrect.
>> 
>> 
>> gcc version 4.5.1 20100506 (prerelease) (GCC)
>> Target: x86_64-apple-darwin10.3.0
>> 
> 
> I just tried it with 4.4.1 and 4.5.0, also works.
> 
> -- Wolfgang

FX and Wolfgang,

Thanks for taking the time to try the example.

Are you by chance using any special configure options to build your 
gfortran? I built mine with the default options from the GFortran Wiki 
(http://gcc.gnu.org/wiki/GFortranSource), as follows:

$ gfortran -v
Configured with: ../gcc-4.6-20100925/configure --prefix=$HOME/gcc-trunk 
--enable-languages=fortran --enable-checking=release --disable-bootstrap
Thread model: posix
gcc version 4.6.0 20100925 (experimental) (GCC)

0
Reply ortp21 (6) 10/14/2010 8:08:16 PM

> Are you by chance using any special configure options to build your 
> gfortran? I built mine with the default options from the GFortran Wiki 
> (http://gcc.gnu.org/wiki/GFortranSource), as follows:
> 
> $ gfortran -v
> Configured with: ../gcc-4.6-20100925/configure --prefix=$HOME/gcc-trunk 
> --enable-languages=fortran --enable-checking=release --disable-bootstrap
> Thread model: posix
> gcc version 4.6.0 20100925 (experimental) (GCC)

What's your target triplet?

-- 
FX
0
Reply coudert (470) 10/14/2010 8:50:57 PM

On 2010-10-14 15:50:57 -0500, FX said:
> 
> What's your target triplet?

Target: x86_64-apple-darwin10.4.0

I just tried the code on Windows using the Equation.com build and it 
worked correctly.

I guess this is too far over my head, like Nick Maclaren said.

0
Reply John 10/14/2010 9:04:42 PM

On 2010-10-14 14:33:09 -0500, nmm1@cam.ac.uk said:

> In article <77ea616d-53bc-4724-8ddc-44465b4027a5@t8g2000yqk.googlegroups.com>,
> John N. <ortp21@gmail.com> wrote:
>> I am trying to create an example which would allow me to catch an
>> exception in C++ during a call to a Fortran subroutine. I want to use
>> this as a crude form of error handling for my program which is mixing C
>> ++ and Fortran using the iso_c_binding module. ...
> 
> Anyone who needs to ask that on a newsgroup doesn't have a hope in
> hell of getting it to work.  Sorry.  Don't bother - you're wasting
> your time - think of another way to do it.
> 
> If you really intend to proceed, get hold of the source of gcc
> (including g++, glibc and gfortran) and investigate what is going
> on.  It won't be quick and it won't be easy.
> 
> Oh, and watch out for the language issues where making it 'work'
> will break features of one or both languages - there are quite a
> lot.
> 
> 
> Regards,
> Nick Maclaren.

Sorry for trying. I was just attempting to not resort to doing what I 
was doing before (writing errors to stdout for testing), to which you 
responded (from my post: "Mixing Languages with gfortran and Visual 
C++"):

>Yes, indeed.  Reasonably expert people can do I/O to different files
>from the two languages, but even that has more gotchas than most
>people realise.  And stdin/stdout/stderr should be handled by one
>language only, or chaos is likely.

With the example I posted today, I was just trying to handle everything 
with one language (C++), I just didn't realize it was so looked down 
upon.

0
Reply John 10/14/2010 9:10:25 PM

> Target: x86_64-apple-darwin10.4.0

Then I have an easy way to guarantee you that it will work: use my own
binaries! :)

They're at http://gcc.gnu.org/wiki/GFortranBinaries#MacOS
Download the link for "Intel (x86_64)".

> I guess this is too far over my head, like Nick Maclaren said.

Nope, Nick is too pessimistic in this case, I think.

I just figured out the difference between your case and mine: you're
using the system C++ compiler with a gfortran from a different version of
GCC. I use a pair of compilers with matching version.

-- 
FX
0
Reply FX 10/14/2010 9:36:58 PM

> With the example I posted today, I was just trying to handle everything
> with one language (C++), I just didn't realize it was so looked down
> upon.

Exceptions should propagate well through Fortran routines if you use
companion C++/Fortran compilers. Don't let Nick deter you from doing it!

-- 
FX
0
Reply FX 10/14/2010 9:38:21 PM

On 2010-10-14 16:36:58 -0500, FX said:

> Then I have an easy way to guarantee you that it will work: use my own
> binaries! :)
> 
> They're at http://gcc.gnu.org/wiki/GFortranBinaries#MacOS
> Download the link for "Intel (x86_64)".

Awesome, I just downloaded them and tried my example. It works! Thanks.

> 
>> I guess this is too far over my head, like Nick Maclaren said.
> 
> Nope, Nick is too pessimistic in this case, I think.
> 
> I just figured out the difference between your case and mine: you're
> using the system C++ compiler with a gfortran from a different version of
> GCC. I use a pair of compilers with matching version.

Ah, so I am. When I built gfortran I did not build a corresponding g++ 
because I figured that the Apple gcc/g++ would be fine for my purposes, 
and it would take less time to build that way haha. I will keep in mind 
that the compiler pairs must be the same version for this to work as 
intended.

Thanks again.

0
Reply John 10/14/2010 9:57:51 PM

In article <i97t8d$pfa$2@news.eternal-september.org>,
FX <coudert@alussinan.org> wrote:
>> With the example I posted today, I was just trying to handle everything
>> with one language (C++), I just didn't realize it was so looked down
>> upon.

It's not looked down on - it's just so far beyond the specifications
that anything may happen.

>Exceptions should propagate well through Fortran routines if you use
>companion C++/Fortran compilers. Don't let Nick deter you from doing it!

If you are the person that I think you are, you should know better.

It is quite easy to get a single error message out of a diddy little
program when it is followed by the program terminating.  But that
is NOT equivalent to getting the feature working.  An expert can
make an educated guess as to what is likely to 'work' and what is
not, but most people don't.  I have done that sort of trick in much
more complicated environments, but I don't do it unless I really
have to, because I know what the issues are.

You can start by considering issues like destructors, I/O buffers,
allocatable arrays, recursion, copy-in/copy-out, etc. and then
move onto the really hairy areas.

I have lost count of the times that I have had less experienced
people say that I am exaggerating such issues, only to have them
come crying to me later saying that their code has suddenly gone
bananas, the debugger is having hysterics, and they can't see why.

It's your funeral.


Regards,
Nick Maclaren.
-1
Reply nmm1 10/14/2010 10:14:36 PM

In article <i97rk1$l0n$1@news.eternal-september.org>,
John N.  <ortp21@gmail.com> wrote:
>
>Sorry for trying. I was just attempting to not resort to doing what I 
>was doing before (writing errors to stdout for testing), to which you 
>responded (from my post: "Mixing Languages with gfortran and Visual 
>C++"):
>
>>Yes, indeed.  Reasonably expert people can do I/O to different files
>>from the two languages, but even that has more gotchas than most
>>people realise.  And stdin/stdout/stderr should be handled by one
>>language only, or chaos is likely.
>
>With the example I posted today, I was just trying to handle everything 
>with one language (C++), I just didn't realize it was so looked down 
>upon.

Now, exactly WHY did you choose to use a problematic feature of
C++ (exceptions) that has no equivalent in Fortran, rather than
just writing the message from the C++ function you called?


Regards,
Nick Maclaren.
0
Reply nmm1 10/14/2010 10:37:46 PM

On 2010-10-14 17:37:46 -0500, nmm1@cam.ac.uk said:
> Now, exactly WHY did you choose to use a problematic feature of
> C++ (exceptions) that has no equivalent in Fortran, rather than
> just writing the message from the C++ function you called?

I am trying to write the message from the C++ function that was called 
from the Fortran code. I did not realize that exceptions were a 
problematic feature of C++. With the example I posted, I was just 
trying to make the code use exceptions, which I commonly use in C++.

So, if I changed the C++ function called to just print out to a stream 
(std::cout, for example) and return normally, than would the code be 
less problematic (all I/O from C++ only)?

My only intent was for the exception to pass right through the Fortran 
code, since it has no equivalent, so the calling C++ code could report 
the error.

Thanks.

0
Reply John 10/14/2010 11:25:11 PM

In article <i983gn$j2a$1@news.eternal-september.org>,
John N.  <ortp21@gmail.com> wrote:
>
>> Now, exactly WHY did you choose to use a problematic feature of
>> C++ (exceptions) that has no equivalent in Fortran, rather than
>> just writing the message from the C++ function you called?
>
>I am trying to write the message from the C++ function that was called 
>from the Fortran code. I did not realize that exceptions were a 
>problematic feature of C++. With the example I posted, I was just 
>trying to make the code use exceptions, which I commonly use in C++.

FAR too many books on computing teach techniques without describing
their limitations and dangers.  It's like teaching people how to
use guns and sending them out to use them, without teaching them
safety techniques.  A good test for whether a book or course is any
good is whether it DOES do that for exceptions.

Bruce Eckel "Thinking in C++" isn't bad, but doesn't cover calling
Fortran, and Bjarne Stroustrup "Programming: principles and practice
using C++" is almost certainly good, too.

>So, if I changed the C++ function called to just print out to a stream 
>(std::cout, for example) and return normally, than would the code be 
>less problematic (all I/O from C++ only)?

Vastly so.  With the minor niggle that it is C++ and not C, it would
even be potentially standard-conforming.  It is the approach that I
recommend, and will restore the ability you had to use the compilers
of your choice (insofar as you had it!)

That doesn't mean that there are NO problems, but that there are
vastly fewer and less likely ones.

>My only intent was for the exception to pass right through the Fortran 
>code, since it has no equivalent, so the calling C++ code could report 
>the error.

Yes.  That is a very reasonable requirement, unless you know the
relevant standards and implementation techniques fairly well.  In
which case you know that it would be damn near impossible to specify
or implement without breaking at least some features of one or both
languages.


Regards,
Nick Maclaren.
0
Reply nmm1 10/15/2010 8:27:02 AM

> It is quite easy to get a single error message out of a diddy little
> program when it is followed by the program terminating.  But that
> is NOT equivalent to getting the feature working.

Depends what you call "the feature". I expect that in general, mixing
broad use of C++ exceptions with broad use of inter-language programming
is a pain, and I wouldn't do it myself.

But that does not equate to it being unsupported, or working by chance or
accident, or anything like it.

In particular, I'd like to ask you why you think that mixing C++
exceptions and calling Fortran subroutines is any less safe than mixing
C++ exceptions and "extern C" functions. The latter is something people
do all the time. With one minor issue (possible buffering in the I/O
library), I do not think it is unsafe (you just need to be very careful).

> It's your funeral.

Well, on a public forum, that's the rule of the game, of course.

-- 
FX
0
Reply FX 10/15/2010 11:47:53 AM

In article <i99f19$3ba$1@news.eternal-september.org>,
FX <coudert@alussinan.org> wrote:
>
>> It is quite easy to get a single error message out of a diddy little
>> program when it is followed by the program terminating.  But that
>> is NOT equivalent to getting the feature working.
>
>Depends what you call "the feature". I expect that in general, mixing
>broad use of C++ exceptions with broad use of inter-language programming
>is a pain, and I wouldn't do it myself.
>
>But that does not equate to it being unsupported, or working by chance or
>accident, or anything like it.

If you are talking about the language definitions (i.e. the standards),
then they demonstrably don't support it, because the only support is for
Fortran calling C.  If you are talking about compilers in general, or
even one in particular, then please post a reference to where they state
that they do, and the constraints that they impose to make it
implementable.

>In particular, I'd like to ask you why you think that mixing C++
>exceptions and calling Fortran subroutines is any less safe than mixing
>C++ exceptions and "extern C" functions. The latter is something people
>do all the time. With one minor issue (possible buffering in the I/O
>library), I do not think it is unsafe (you just need to be very careful).

I gave you a list of problematic areas.  I suggest that you read the
sections of the standards about destructors (both exceptions inside them
and what happens when an exception is raised), final procedures,
C++->Fortran->C++->Fortran->C++, etc.  You could then move onto the
consequences of the association rules (especially delights like
INTENT(OUT), allocatable arguments, arguments that may derive from
Fortran used when raising or handling the exception) when combined with
this sort of activity - and, if you don't start gibbering at that point,
you haven't understood them.

That may sound arrogant but is, regrettably, accurate.  I worked as
a sort of consultant on one of the only two relatively modern projects
I know of that attempted to support exception handling in a multi-language
context, and the issues are evil to a degree that few people realise.
Bjarne didn't have major headaches with the C++ design because it was
conceptually easy, and that was starting from just one, conceptually
trivial, language.


Regards,
Nick Maclaren.
0
Reply nmm12 (898) 10/15/2010 12:32:36 PM

17 Replies
408 Views

(page loaded in 0.176 seconds)

Similiar Articles:
















7/27/2012 1:29:51 PM


Reply: