Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29253 Discussions

Can I catch Fortran RTL errors in C?

rzamudio
Beginner
1,722 Views

I am calling a fortran function from C++ code in a try/catch block. For certain inputs, I get the following RTL error:

forrtl: severe (64): input conversion error, unit -5, file Internal Formatted Read

I would like to catch this error, and any others, in the C code and print a message like "the Fortran function had an error" to a file. The code is running remotely, so I don't want the RTL error window to come up.

My code for windowsis :

retval = putenv("FOR_DISABLE_DIAGNOSTIC_DISPLAY=TRUE");

try
{
retval = CHARMM(); // The fortran function
switch (retval) {
case 0: fprintf(stderr, "SUCCESS - Charmm exited with code %i. ", retval);
break;
.....
}
}
catch ( ... ) // Catch any errors
{
fprintf(stderr,"Charmm caused an exception! ");
}

Right now I am just looking for any exception, but if possible would like more information. This code has been able to catch other error caused by the function, stack overflow for example, but doesn't seem to catch any RTL errors. Is this possible?

0 Kudos
10 Replies
Jugoslav_Dujic
Valued Contributor II
1,722 Views
The problem is that RTL functions don't raise an exception. Here's a copy/paste (+attachment) which uses a trick to override default for_emit_diagnostic routine. However, I'm not sure if it works for I/O errors -- I think not. If not, you can insert stat=iErr in all READ statements and do something on that (e.g. call RaiseException yourself).


It actually comes from this Intel Forum thread:

http://softwareforums.intel.com/en-us/forums//topic/51696

Since exception handling is somewhat changed in IVF, I added
routine for_emit_diagnostic to Steve's SEHTEST example. It effectively
overrides built-in IVF mechanism (hardcoded call to for_emit_diagnostic
from the run-time library), by raising an exception explicitly itself
(EXCEPTION_ACCESS_VIOLATION is as good as any).

If your main program is in Fortran, you have to create some sort of
C++ wrappers with __try/__except around your (critical) function calls
and link them either to dll or to the main application.

| but where should this subroutine been called?

Nowhere -- it's called automagically when a IVF-handled exception
occurs. The code inserted by compiler into the code calls this
function. If it's in the RTL (default), it displays the annoying
message box; if it's your own, it does what you want.
(Take just a brief look into disassambly window for a line
with e.g. array operation, with "Array bounds checking" on).

The trick wasn't necessary with CVF -- it used to throw proper
exception on array bounds exceeded rather than emit the annoying
"Run-time error" message box.

| I've thus added the for_emit_diagnostic subroutine, which works fine
| in debug mode. Nevertheless, as soon as I compile my program in
| release mode I got the the following error: for_emit_diagnostic
| already defined in for_emit_diagnostic.obj :-((((((

Yes, I forgot to mention that glitch...

The "technique" in case is one of substituting default RTL routines;
as result, there are two copies of for_emit_diagnostic: yours and the
default RTL one.

If you link with a dll version of RTL, the thing works fine: your
routine always precedes RTL one. If you link with a static version
of RTL, you're likely to get the LNK2005 (already defined in...).

To overcome the problem, either link the dll with dll RTL (but you'll
have to redistribute libifcorert.dll), or add

/force:multiple

to the Properties/Linker/Additional options. (That might give you
a warning, but it will do the Right Thing).

0 Kudos
jeanvezina
Beginner
1,722 Views

Eventually, Intel should extend the Fortran compiler itself to handle Structured Exception Handling from within Fortran programs without resorting to C wrappers.John Reid made proposals in the past to add exception handling in Fortran using some block contructs. Intel could use that syntax as a starting point.

Best regards,

Jean Vezina

0 Kudos
rzamudio
Beginner
1,722 Views
I added my for_emit_diagnostic at the end of my fortran function, but it isn't being called.

I used force:multiple to solve the link error, but it is the original for_emit_diagnostic that executes (I still get the RTL error box).

I am using IVF 9.0 and can't open the sample project, so I'm doing my best to reproduce what you've done. Is the version an issue, or maybe I'm missing something?
0 Kudos
rzamudio
Beginner
1,722 Views
... also, if I run the debug version, the exception is caught.
0 Kudos
Steven_L_Intel1
Employee
1,722 Views
The RTL doesn't signal an exception for I/O errors unless it sees that the debugger is active.
0 Kudos
jjfait
Beginner
1,722 Views
The RTL doesn't signal an exception for I/O errors unless it sees that the debugger is active.
Im a little confused on this topic and wondering if there is a better forum location on this matter. Im also trying to call a fortran DLL from c(#) and am wondering how to catch exceptions. This says to add Subroutine for_emit_diagnostic and then what do you do in the subroutine I don't see it being called when a run-time error is found, thanks
jeremy
0 Kudos
Steven_L_Intel1
Employee
1,722 Views
What kind of error do you want to catch? As I noted above, errors detected by the software, such as array bounds or I/O errors, are not signaled in a way that an exception handler can "catch".
0 Kudos
jjfait
Beginner
1,722 Views
What kind of error do you want to catch? As I noted above, errors detected by the software, such as array bounds or I/O errors, are not signaled in a way that an exception handler can "catch".
Ok that answers a couple questions, i wanted to catch invalid array indexes, divide by zero or overflows, and invalid file directories
0 Kudos
Steven_L_Intel1
Employee
1,722 Views
Array index errors and invalid file directories you cannot "catch".

Integer divide by zero you can catch. Floating divide by zero, by default, yields a NaN. You can specify /fpe:0 to make that an exception which you can catch. Similarly, floating overflow yields an Inf which /fpe:0 will make into an exception. Integer overflow is not detected in Fortran code.
0 Kudos
jjfait
Beginner
1,722 Views
Array index errors and invalid file directories you cannot "catch".

Integer divide by zero you can catch. Floating divide by zero, by default, yields a NaN. You can specify /fpe:0 to make that an exception which you can catch. Similarly, floating overflow yields an Inf which /fpe:0 will make into an exception. Integer overflow is not detected in Fortran code.
thanks
0 Kudos
Reply