Непонятное поведение стека в программе, скомпилированной G77

У меня есть смесь C++ и Fortran 77, все скомпилированные с G77. В основном это C++, но он вызывает ODE-решатель DVERK, который затем вызывает глобальную функцию C для получения производной (объявленной с помощью __stdcall). Все работает нормально, пока я не получу странный SIGSEGV.

Я отследил это, и это было потому, что esp снижался ниже границы своего сегмента. Это произошло потому, что DVERK содержит ** оператор, который внутренне является вызовом функции с двумя значениями двойной точности, передаваемыми по значению в стеке, для 16 байтов. Функция возвращает ответ, но затем я вижу эту инструкцию:

sub 0x10,%esp

который уменьшает указатель стека на 16 байт, как если бы он помещал аргументы обратно в стек (?) G77, кажется, делает это после каждого вызова функции, и обычно это не причиняет вреда, поскольку указатель стека не изменяется. Тем не менее, в случае ** указатель стека остается уменьшенным, и если этот код выполняется достаточно раз, уменьшение продолжается до тех пор, пока я не получу SIGSEGV. (Если имеется достаточно стекового пространства, эта проблема не появляется, потому что возврат из DVERK очищает его.)

Я пытался заменить код a**b с dexp(dlog(a)*b), но происходит то же самое, за исключением того, что это происходит в два этапа, 8 байт после dlogи 8 байт после dexp,

Должно быть, я что-то не так делаю при настройке соглашений о вызовах, используемых G77, в сравнении с его библиотекой времени выполнения. Экспертиза ценится.

1 ответ

В эту эпоху способ смешать C или C++ с Fortran - это использовать ISO-C_Binding. Из C++ вызывайте с помощью extern C. В языке Fortran (англоязычное слово) привязка Fortran ISO C для вызываемой процедуры. Это заставит Fortran использовать соглашение о вызовах C (ABI). Тогда вам не нужно понимать внутренности компилятора. Для этого вам придется использовать более современный компилятор Fortran, чем g77, например, gfortran. gfortran полностью способен компилировать FORTRAN 77. Официально ISO-C-Binding является частью Fortran 2003 - вы можете написать оболочку между C++ и существующим FORTRAN 77.

Существует тег Stackru, объясняющий привязку ISO-C: https://stackru.com/tags/fortran-iso-c-binding/info

Другие вопросы по тегам