- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am using Compaq Visual Fortran 6.6.0 to create a DLL. It is called from a Visual Basic 6 ActiveX single-threadedmain program. The DLL writes to a log file. When it runs into a floating point exception (fpe)I would like it to jump to aroutine that writes an entry to the log file, closes the file,and then stops execution of the program.
Igatheredthis relevant info:
SIGNALQQ does not work in a VB-VF application. Try writing a C routine (called from the Fortran DLL) that uses "signal" to set the callback routine in case of an fpe, thereby bypassing SIGNALQQ.
Wrote this C-code:
#include
#include
void __cdecl fphandler( int sig, int num);
void __stdcall HAND_FPE ( int sig, int num); //Fortran call
//Entry point for setting up where to jump to in case of an exception:
int __stdcall CSIGNALQQDLL() {
//Assumption: floating point control word has already been masked as desired
if ( signal( SIGFPE,(void (__cdecl *)(int)) fphandler) == SIG_ERR ) {
return -1;}
else {
return -2;
}
}
void __stdcall TESTBYRAISE(){
raise(SIGFPE);
}
// This is where we jump to in case of an exception:
void fphandler ( int sig, int num){
_fpreset();
// Make call to a Fortran-written subroutine
HAND_FPE(sig, num);
}
In the Fortran DLL there are these code fragments:
i4_i = CSIGNALQQDLL() ! Set the exception handler
CALL GETCONTROLFPQQ(FPEcontrol)
i4_i = FPEcontrol
call BIC(0,i4_i)
call BIC(2,i4_i)
call BIC(3,i4_i)
FPEcontrol = i4_i
CALL SETCONTROLFPQQ(FPEcontrol)
CALL TESTBYRAISE
with the following effects:
(*) FPE control word is set successfully
(*) CSIGNALQQDLL seems to set the call-back routine successfully because of the next item : ...
(*) The call to TESTBYRAISE succeeds in calling the call-back routine fphandler because the call to the Fortran subroutine HAND_FPE takes place (writes to the log file)
(*) However, when I remove the call to TESTBYRAISE and let the program run into an actualfpe then the call-back routine is not called.
Please help me make this work correctly! Thank you,
Robert Rackl
The Boeing Company
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- I assume you didn't forget to build the dll with /fpe:0, did you?
- What does debugger say when the actual program (is supposed to) generate the FPE? It ought at least emit the message: ..."Floating point exception"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did build with /fpe:0
When Iintentionally let it run into a divide by zero, the debugger says
First chance exception in PlotTBL.exe (PFJARP4.DLL): 0xC000008E:Float Divide by Zero
and then it exits to the calling program instead of jumping to the call-back routine. The calling program (in VB6)then reports the Divide by Zero error and aborts.
The linker does give me 2 warnings which I do not know how to resolve:
warning LNK4075: ignoring /EDITANDCONTINUE due to /INCREMENTAL:NO specification
warning LNK4098: defaultlib "LIBCD" conflicts with use of other libs; use /NODEFAULTLIB:library
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For the start, the LNK4098 shows a discrepancy between run-time libraries you have on C++ tab (Debug single-threaded) and on Fortran tab (probably Debug multi-threaded dll). I'd recommend trying static (non-dll) libraries. It might solve the problem as well, although it's just a wild stab in the dark.
As far as I get it (and I might easily be wrong), the C run-time library somewhere has a (pseudo-code)
try {...
}
catch (_fpexception e)
{fphandler(e.sig, e.num)
}
What I don't get is, where is that try...catch physically located -- in run-time library or injected directly into the code by the C compiler; if the latter, you're likely beaten. Someone from Intel RTL team might have a more useful comment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
http://www.xeffort.com/fortran/misc/MixLang.zip
(it's not minimal, but you'll see the point easily)
I built (Debug configuration) with /fpe:0, but I had to set up floating-point exception mask via SETCONTROLFPQQ. It appears that something in C++ RTL or Windows sets up the FP exception mask to "masked" by default so it has to be unmasked. I can get the same effect by placing
_controlfp(0, _EM_ZERODIVIDE);in the C++ calling code (presumably, the same would do if you have a C++ wrapper within the dll).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you haven't already, it's a good idea to upgrade to 6.6C, although I don't see that it could improve something.
For what it's worth, the assembly code generated for the line f=f/0. is:
53: f = f/0.
1000139C fld dword ptr [ebx]
1000139E wait
1000139F fdiv dword ptr [string "crtdll.c"+0FFFFFFF4h (10003048)]
100013A5 wait
100013A6 fstp dword ptr [ebx]
100013A8 waitFstp instruction raises a FP exception if any (http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetica2.html), and the catch(...) block is executed immediately after.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
SEH works just fine for both CVF and IVF, whether with .exe's or .dll's. However, if you're linking incrementally, don't, it prevents traceback from giving any useful info.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
You can try FOR_SET_FPE(...) , see example below.
It's works for me. My main application is MFC C++ application and Fortran in static library. I use VC++(VS2005) and Intel Fortran 9.1 .
Regards,
Oleg.
subroutine test_command3
USE IFCORE
IMPLICIT NONE
real*4 res_uflow, res_oflow
real*4 res_dbyz, res_inv
real*4 small, big, zero, scale
INTEGER*4 OLD_FPE_FLAGS, NEW_FPE_FLAGS
NEW_FPE_FLAGS = FPE_M_TRAP_DIV0+FPE_M_MSG_DIV0 + FPE_M_TRAP_UND+FPE_M_MSG_UND + FPE_M_TRAP_OVF+FPE_M_MSG_OVF + FPE_M_TRAP_INV+FPE_M_MSG_INV
OLD_FPE_FLAGS = FOR_SET_FPE(NEW_FPE_FLAGS)
small = 1.0e-30
big = 1.0e30
zero = 0.0
scale = 1.0e-10
! IEEE underflow condition (Underflow Raised)
res_uflow = small * scale
write(6,100)"Underflow: ",small, " *", scale, " = ", res_uflow
! IEEE overflow condition (Overflow Raised)
res_oflow = big * big
write(6,100)"Overflow: ", big, " *", big, " = ", res_oflow
! IEEE divide-by-zero condition (Divide by Zero Raised)
res_dbyz = -big / zero
write(6,100)"Div-by-zero: ", -big, " /", zero, " = ", res_dbyz
! IEEE invalid condition (Invalid Raised)
res_inv = zero / zero
write(6,100)"Invalid: ", zero, " /", zero, " = ", res_inv
100 format(A14,E8.1,A2,E8.1,A2,E10.1)
end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I is not apparent how frequently your application calls the DLL. If the calling frequency is low relative to the runtime inside the DLL then the following techniques may be useful.
1) At the entry point(s) to the DLL call the function FTELL(iUnitLogFile) to obtain the current output position.
2) Write to the Log File "Floating Point Exception" and call FLUSH(iUnitLogFile)
3) Prior to any legitimate writes to the log file within the DLL perform an FSEEK to the file position in front of the "Floating Point Exception" marker.
4) Following any legitimate writes to the log file within the DLL perform steps 1) and 2)
5) Just prior to exit from DLL perform an FSEEK to the file position in front of the "Floating Point Exception" marker.
Consider changing "Floating Point Exception" to "Fatal Error occured in xyz.DLL" since it will also catch not only FPE but invalid memory access, etc...
The aboveis a fall-back suggestion.
An alternartve is to create a monitoring application that has a pipe to the current .DLL. Then in the .DLL you can write tracing information as to not only Entry and Exit of the DLL but also of major waypoints within the DLL. Then if the application Ab-Ends within the DLL you will have more information available to diagnose the problem.
Good luck.
Jim Dempsey
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page