У меня есть смесь 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, по отношению к его библиотеке времени выполнения. Экспертиза приветствуется.