Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
FORTRAN和C的互操作性—REAL(4)s是否会太小?_C_Interop_Stack_Fortran_Stack Corruption - Fatal编程技术网

FORTRAN和C的互操作性—REAL(4)s是否会太小?

FORTRAN和C的互操作性—REAL(4)s是否会太小?,c,interop,stack,fortran,stack-corruption,C,Interop,Stack,Fortran,Stack Corruption,我们在一些英特尔FORTRAN代码中遇到了一些奇怪的崩溃,我最终跟踪到: L_F = EXP(-L_B2*L_BETASQ*L_DS) 其中-L_B2*L_BETASQ*L_DS项的计算值约为-230。碰巧,EXP(-230)的计算结果约为1e-100。在所有其他已知情况下,L_DS要小得多,导致EXP的最小(已知)返回值约为1e-50,这不会导致错误 FORTRAN计算子句EXP(-230)后,您将得到: forrtl: severe (157): Program Exception - a

我们在一些英特尔FORTRAN代码中遇到了一些奇怪的崩溃,我最终跟踪到:

L_F = EXP(-L_B2*L_BETASQ*L_DS)
其中-L_B2*L_BETASQ*L_DS项的计算值约为-230。碰巧,EXP(-230)的计算结果约为1e-100。在所有其他已知情况下,L_DS要小得多,导致EXP的最小(已知)返回值约为1e-50,这不会导致错误

FORTRAN计算子句EXP(-230)后,您将得到:

forrtl: severe (157): Program Exception - access violation
Image              PC        Routine            Line      Source
但没有其他信息

异常157通常与互操作性有关,您无法在FORTRAN中调试到EXP,因为它找不到特定的.c文件-这可能意味着EXP是用c实现的(这让我感到惊讶)

我的假设是FORTRAN已经在C中实现了EXP,但是接口无法将小于1e-100的浮点转换为实(4)s。因为我以前认为浮点和实(4)s在字节方面是相同的,所以我不能支持这个假设——而且我在任何地方都找不到关于它的任何东西

在我关闭这个bug之前,有人能证实或否定我的假设吗?或者给我提供另一个

致以最良好的祝愿

迈克

编辑:我将此问题标记为已回答,因为高性能标记已回答了直接的问题

不幸的是,我的假设是错误的——我试图通过这样做来解决问题:

L_ARG = L_B2*L_BETASQ*L_DS

IF (L_ARG .GT. 230.0) THEN
    L_F = 0.0
ELSE
    L_F = EXP(-L_ARG)
ENDIF
不幸的是,异常现在(显然)发生在L_ARG.GT中。230.0条款。这要么意味着在发布模式下的调试比我想象的要糟糕,要么是某种“存储”的浮点错误(请参阅)。

Fortran没有(必要)在C中实现任何东西。标准内部函数的实现是特定于编译器的;通常会发现实现调用
libm
或它的一个亲戚。从英特尔(或任何其他编译器编写者)的角度来看,这是有意义的,用您喜欢的任何语言编写一个健壮、快速的
exp
实现,并从Fortran、C、Ada、COBOL和所有其他您听说过的语言中调用它。甚至用C写也可能是明智的。因此,你的部分假设可能是正确的

然而,除非您明确地编写C代码和Fortran代码,并从中生成一个二进制代码,否则实际上没有任何互操作性(在Fortran标准意义上),所有这些肮脏的细节都(或应该)对您隐藏;编译器应该生成对它用来实现
exp
的任何库的正确调用,并获取返回值,无论它们可能包括
NaN
s和类似值

当然,对于4字节的实数,
exp(-230)
的值是
0.00000000
,但我看不出为什么使用C编写的库的Fortran程序会引发访问冲突,因为它遇到了这些数字。我认为更可能的情况是,您的程序中的其他地方出现了错误,可能是试图访问数组边界之外的数组元素,并且您的运行时无法在源代码中的正确位置识别它。这并不罕见

编辑

在(重新)阅读问题之前,我写了这篇关于互操作性的文章。既然您已经说明您正在使用互操作性功能,那么它可能会引起您的兴趣或使用

您当然不能依赖Fortran的
real(4)
和C的
float
是相同的;很有可能,但不确定。大多数现代Fortran编译器(包括Intel)使用的种类类型参数与其表示形式中的字节数相匹配,因此代码
4
表示您正在处理一个4字节的实数,在符合IEEE-754的处理器上,该实数应与C
float
相同。Fortran标准不要求这些种类类型参数与用于表示数字的字节数之间存在任何对应关系。检查编译器文档或做一些测试总是值得的

如果您关心互操作性,您可能应该使用Fortran的固有特性。例如,如果你

use :: iso_c_binding
您有许多可用的常量,包括
C_FLOAT
,可以这样使用:

real(C_FLOAT) :: a_fortran_float
如果您的Fortran编译器支持这一点,那么
a_Fortran_float
应该与配套处理器上的C float匹配。这个最后一个术语被留下了一些未定义的,在实践中,来自同一个稳定的编译器看起来总是是伙伴,对于不同的STARESS有时是的,有时不是。英特尔FORTRAN和C和C++编译器似乎是所需意义上的伙伴。得知英特尔FORTRAN和MSC++编译器不能很好地配合在一起,这并不奇怪。
我对C的模糊记忆包括一个不确定性,即
float
是标准化的,在这种情况下,如果不测试或阅读文档,您就无法确定在互操作的这一侧是否真的有一个4字节的IEEE单精度浮点数。

谢谢,Mark-所有有趣的东西。该二进制文件实际上是一个混合的FORTRAN-C++二进制文件,使用VS2010(所以VC++与Intel FORTRAN配合使用),但我认为这一点不值得一提。我只能在发布模式下单步执行代码,因为在调试模式下不会触发问题,但在发布模式下,很明显是EXP调用导致了问题。事实上,在我们较新的工作代码中这一点已经改变,这也表明(但不能证明)是EXP(-230)导致了问题。我将试着给出一个单独的例子……我指的是我答案的第三段。打开运行时数组边界检查和编译时过程参数检查。由于寄存器存储优化和实际指令实现了