0

I've got a mixture of C++ and Fortran 77, all compiled with G77. It is mostly C++, but it calls the ODE-solver DVERK, which then calls back to a global C function to get the derivative (declared with __stdcall). It's all been working fine, until I get a strange SIGSEGV.

I tracked that down, and it was because the esp was decreasing below its segment boundary. The reason it did that is that DVERK contains the ** operator, which internally is a function call with two double-precision values passed by value on the stack, for 16 bytes. The function returns the answer, but then I see this instruction:

sub 0x10,%esp

which decrements the stack pointer by 16 bytes, as if it were putting the arguments back on the stack (?) G77 seems to do this after every function call, and usually it does no harm because the stack pointer is unchanged. However, in the case of ** the stack pointer remains decremented, and if that code is executed enough times, the decrementation adds up until I get the SIGSEGV. (If there is sufficient stack space, this problem doesn't appear because the return from DVERK cleans it up.)

I tried replacing the code a**b with dexp(dlog(a)*b), but the same thing happens, except it happens in two steps, 8 bytes after dlog, and 8 bytes after dexp.

There must be something I'm doing wrong in setting up the calling conventions used by G77 vis-a-vis its run-time-library. Expertise appreciated.

4

1 回答 1

2

在这个时代,将 C 或 C++ 与 Fortran 混合使用的方法是使用 ISO-C_Binding。在 C++ 中,使用 extern C 调用。在 Fortran 中,使用(英文单词)Fortran ISO C 绑定来调用被调用的过程。这将导致 Fortran 使用 C 的调用约定 (ABI)。然后您不必了解编译器内部结构。为此,您必须使用比 g77 更现代的 Fortran 编译器,例如 gfortran。gfortran 完全能够编译 FORTRAN 77。ISO-C 绑定是 Fortran 2003 的一部分——您可以在 C++ 和现有的 FORTRAN 77 之间编写一个包装器。

有一个解释 ISO-C-Binding 的 Stackoverflow 标签:https ://stackoverflow.com/tags/fortran-iso-c-binding/info

于 2014-09-07T00:27:10.820 回答