Mik*_*ler 2 c stack interop fortran stack-corruption
我们在一些英特尔FORTRAN代码中遇到了一些奇怪的崩溃,我最终将这条线跟踪到:
L_F = EXP(-L_B2*L_BETASQ*L_DS)
Run Code Online (Sandbox Code Playgroud)
-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
Run Code Online (Sandbox Code Playgroud)
但没有其他信息.
异常157通常与互操作性有关,并且您无法在FORTRAN中调试EXP,因为它无法找到特定的.c文件 - 这可能意味着EXP在C中实现(我觉得这很令人惊讶).
我的假设是FORTRAN在C中实现了EXP,但是接口不能将小于1e-100的浮点数转换为REAL(4)s.正如我之前认为浮点数和REAL(4)s在字节方面相同,我无法支持这个假设 - 我无法找到任何关于它的东西.
在我关闭这个错误之前,任何人都可以确认或否认我的假设 - 或者向我提供另一个假设吗?
最好的祝福,
麦克风
编辑: 我将把这个问题标记为已回答,因为高绩效标记已回答了当前的问题.
不幸的是,我的假设是不正确的 - 我试图将这个问题陷入困境:
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
Run Code Online (Sandbox Code Playgroud)
不幸的是,现在(显然)例外发生在L_ARG .GT中.230.0条款.这或者意味着Release模式下的调试比我想象的要糟糕,或者它是某种"存储的"浮点错误(当将float输入到stringstream时,请参阅"浮点无效操作").
Fortran没有(必然)在C中实现任何东西.标准内在函数的实现是特定于编译器的; 通常会发现实现调用libm或其中一个亲属.从英特尔(或任何其他编译器作者)的观点来看,这是有道理的,用exp任何语言编写一个强大而快速的实现,并从Fortran,C,Ada,COBOL以及所有其他语言中调用它.听说.将它写在C中甚至可能是明智的.因此,您的假设的一部分可能是正确的.
但是,除非您明确地编写C代码和Fortran代码并从中创建单个二进制代码,否则实际上没有任何互操作性(在Fortran标准意义上),所有脏的细节都是(或应该)对您隐藏; 编译器应该生成对它用来实现的任何库的正确调用,exp并获得返回值,无论它们包括NaNs和类似物.
当然,值exp(-230)是0.000000004字节的实际值,但我认为没有理由为什么使用C编写的库的Fortran程序会引发访问冲突,因为它遇到了这些数字.我认为你的程序中其他地方出现错误的可能性要大得多,可能是试图访问数组范围之外的数组元素,并且运行时无法在源代码中的正确位置识别它.这并不罕见.
编辑
在重新阅读问题之前,我写了关于互操作性的内容.既然您已经澄清了您正在使用互操作性功能,那么它可能会引起兴趣或使用......
你当然不能依赖你的Fortran real(4)和你的C float是相同的; 很可能但不确定.大多数现代Fortran编译器(包括Intel)使用与其表示中的字节数匹配的类型参数,因此代码4表明您正在处理4字节实数,在IEEE-754兼容处理器上应该是与C相同float.Fortran标准不要求那些类型参数与用于表示数字的字节数之间有任何对应关系.总是值得检查您的编译器文档或进行一些测试.
如果您担心互操作性,那么您应该使用Fortran的内在功能.例如,如果你
use :: iso_c_binding
Run Code Online (Sandbox Code Playgroud)
你有许多常量,包括C_FLOAT可以这样使用的常量:
real(C_FLOAT) :: a_fortran_float
Run Code Online (Sandbox Code Playgroud)
如果您的Fortran编译器支持此功能,a_fortran_float则应匹配协同处理器上的C float .这个最后一个术语有点不明确,实际上来自同一个稳定的编译器似乎总是同伴,对于不同的稳定,有时是有时没有.英特尔Fortran和C和C++编译器似乎是所需意义上的伴侣.得知英特尔Fortran和MS C++编译器不能很好地协同工作并不会让我感到惊讶.
我对C的模糊回忆包括float标准化的不确定性,在这种情况下,如果没有测试或阅读文档,你无法确定你确实在那一侧有一个4字节的IEEE单精度浮点数.你的互操作性.