2014-09-06 4 views
0

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

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

sub 0x10,%esp 

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

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

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

ответ

2

В эту эпоху способ смешивания 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.

Существует тег Stackoverflow, который объясняет ISO-C-Binding: https://stackoverflow.com/tags/fortran-iso-c-binding/info

+0

"Era"? :) У меня есть часть «extern C», которая отлично работает. Я не сделал решительный шаг к gfortran, главным образом потому, что есть тонна «технического долга», чтобы идти по этому маршруту. Но спасибо за информацию. Я проверю это. –

+0

Невозможно понять, для перехода с g77 на gfortran. Вариантов компилятора '-ffixed-form -ffixed-line-length-none', вероятно, будет достаточно для компиляции существующего кода FORTRAN 77. –

+0

@MikeDunlavey Я бы даже попробовал переключиться на 'gfortran' и оставить другие изменения, если этого не достаточно. Это вполне можно. –

Смежные вопросы