Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

Segmentation Fault on First Fortran Runtime Library Error with C++ main()

Allen_Barnett
Beginner
2,384 Views

I have an application which has a C++ main() and which links in a Fortran library. We try to make sure that if a Fortran run-time library error occurs, the program has some way to report it. In the program below, the Fortran code delibrately causes a run-time error, but instead of printing the error and the traceback, something in the Fortran run-time library simply aborts. Here is the C++ main program (main.cpp):

[cpp]

extern "C" gen_error ( void );

int main( )

{

gen_error();
}

[/cpp]

and here is the Fortran part (gen_error.f90)

[fortran]

subroutine gen_error ( ) bind(c)

real, allocatable :: a(:)

allocate a(10)

allocate a(10) ! Can't allocate an allocated array

end subroutine gen_error

[/fortran]

When I build this:

[plain]

$ icc -c main.cpp

$ ifort -o main main.o -fexceptions gen_error.f90 -cxxlib

$ ./main

Segmentation fault
[/plain]
Running it under valgrind shows (in part):

[plain]

==8722== Jump to the invalid address stated on the next line
==8722==    at 0x0: ???
==8722==    by 0x404FAD: for__issue_diagnostic (in /scratch/shared/src/main)
==8722==    by 0x403269: for_alloc_allocatable (in /scratch/shared/src/main)
==8722==    by 0x402C55: wha (in /scratch/shared/src/main)
==8722==    by 0x402B5C: main (in /scratch/shared/src/main)
==8722==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==8722==
==8722==
==8722== Process terminating with default action of signal 11 (SIGSEGV)
==8722==  Bad permissions for mapped region at address 0x0
==8722==    at 0x0: ???
==8722==    by 0x404FAD: for__issue_diagnostic (in /scratch/shared/src/main)
==8722==    by 0x403269: for_alloc_allocatable (in /scratch/shared/src/main)
==8722==    by 0x402C55: wha (in /scratch/shared/src/main)
==8722==    by 0x402B5C: main (in /scratch/shared/src/main)
[/plain]

It kind of looks like the run-time has not warmed up enough to emit the error message. Is there a Fortran run-time initialization routine we should be calling before entering the Fortran the first time from the C++ side?

This is with icc/ifort 12.1.2 20111128 on a CentOS 5.6 system with GCC 4.3.2.

Thanks,

Allen

0 Kudos
11 Replies
Steven_L_Intel1
Employee
2,384 Views
Try compiling the Fortran code with -fexceptions And yes, you should call for_rtl_init_ from your C++ main program. Read about it in the Fortran documentation but generically: for_rtl_init_ (&argc, argv);
0 Kudos
Kevin_D_Intel
Employee
2,384 Views
Steve already answered, but since I had already prepared it, I'll post anyway. Add a call to for_rtl_init_ in the C main and add -nofor-main -traceback to the ifort command-line. [cpp] extern "C" void gen_error ( void ); extern "C" void for_rtl_init_ (int *, char **); int main( ) { int argc; char **argv; for_rtl_init_ (&argc, argv); gen_error(); } [/cpp] [bash] ifort -nofor-main -traceback -o main main.o -fexceptions gen_error.f90 -cxxlib [/bash] That returns a call stack like: [plain] $ ./main forrtl: severe (151): allocatable array is already allocated Image PC Routine Line Source main 0000000000463B4A Unknown Unknown Unknown main 0000000000462646 Unknown Unknown Unknown main 0000000000434EF0 Unknown Unknown Unknown main 000000000041B25E Unknown Unknown Unknown main 000000000040650A Unknown Unknown Unknown main 0000000000402C45 gen_error 4 gen_error.f90 main 0000000000402B47 Unknown Unknown Unknown libc.so.6 000000389DC1ECDD Unknown Unknown Unknown main 0000000000402A49 Unknown Unknown Unknown [/plain]
0 Kudos
Allen_Barnett
Beginner
2,384 Views
Great! That fixes my example problem. I'll try it out in my main code (if the cluster is ever available again :-). Thanks, Allen
0 Kudos
Allen_Barnett
Beginner
2,384 Views
Hi: I guess there is still something I'm missing here. Adding a call to for_rtl_init to my real program does not stop the segmentation fault. The difference appears to be that my real program has a try/catch block surrounding the call which produces the Fortran run-time error. If I add a try/catch block to my example program: [cpp] extern "C" gen_error ( void ); int main( ) { int argc; char **argv; for_rtl_init_ (&argc, argv); try { gen_error(); } catch ( ... ) { std::cout << "Caught an exception?" << std::endl; } } [\cpp] the program runs to completion, but it does not print "forrtl: severe (151): allocatable array is already allocated". Instead I get: [plain] $ icpc -fexceptions -c -g main.cpp $ ifort -nofor-main -traceback -o main main.o -fexceptions gen_error.f90 -cxxlib $ ./main Caught an exception? forrtl: severe (174): SIGSEGV, segmentation fault occurred [\plain] Also, in the absence of the print statement in the catch block, the program doesn't print anything at all. I attached the valgrind output from running this program. Thanks, Allen
0 Kudos
Steven_L_Intel1
Employee
2,384 Views
I'm not seeing any kind of segfault when I try your example. I get what Kevin showed. I will comment that you won't be able to catch a Fortran-generated error in a try-catch block. In the next major release (second half of 2013) we're adding a method of "registering" a handler that gets called when a Fortran error is to be raised. -fexceptions simply allows exceptions generated in code called from Fortran to pass through Fortran frames.
0 Kudos
Steven_L_Intel1
Employee
2,384 Views
I am going to guess that your actual Fortran code is different from what you posted above. Pretty easy guess, since what you posted won't compile as it is missing parentheses in the allocate statements. Please don't paraphrase or quote from memory - show us the actual code.
0 Kudos
Allen_Barnett
Beginner
2,384 Views
Hi Steve: I'm very sorry that my example wasn't better thought out. I have attached a tar file with a directory containing the exact code along with a Makefile and the output from the session. If I build the program and run it, I get no output. I ran my example under valgrind, too; it shows a lot of warnings about uninitialized variables and problems unwinding the stack (see valgrind.txt). This was built with ifort/icpc 12.1.2 on RHEL 6.3 with GCC 4.4.6 and GLIBC 2.12. The tar file contains a typescript file with the output from my test (basically showing that no output is produced). I tried this on windows with ifort 12.0.1.127 and cl 16.00.30319.01 (vs2010) and it actually works OK. It prints the "array is already allocated" message and the traceback. I am not attempting to catch the Fortran runtime library error. In my real code, the Fortran periodically makes a callback into the C++. It's possible for that callback to throw an exception and that is what I'm trying to catch. Having the Fortran throw a catchable error would be great! But, all I want my current code to do is print the error and exit (i.e., call abort). Thanks, Allen
0 Kudos
Allen_Barnett
Beginner
2,384 Views
Hi: We upgraded our linux compilers to icpc/ifort 13.0.1 20121010 and I still see the same behavior (i.e., nothing is written to the console). Are you able to reproduce my results or do I need to create a more realistic test case? Thanks, Allen
0 Kudos
Steven_L_Intel1
Employee
2,384 Views
I can reproduce the no-output but I think what is happening is that your catch block is dismissing whatever error is occurring - and that's not the "already allocated" error which is not raised as an exception. If I add a printf there, it prints. I'm going to ask our library folks to take a look at it.
0 Kudos
Steven_L_Intel1
Employee
2,384 Views

We found that the "stack unwind" code we were calling, part of a C library, "knew" that the main program was C++ and effectively disabled the Fortran traceback code.  We have found a workaround for this for a future release.

0 Kudos
Steven_L_Intel1
Employee
2,384 Views

This should be resolved in the 14.0 compiler.

0 Kudos
Reply