#fortran #gfortran
#fortran #gfortran
Вопрос:
Я пытаюсь вызвать подпрограмму SPLEV библиотеки FITPACK с помощью двух функций (‘wer’ и ‘qwe’), вложенных одна в другую (код приведен ниже).
Следующее сообщение появляется при выполнении скомпилированной программы:
QWE
Программа получила сигнал SIGSEGV: ошибка сегментации — недопустимая ссылка на память.
Обратная трассировка для этой ошибки:
0 0x7F3EE4BF3E08
1 0x7F3EE4BF2F90
2 0x7F3EE453A4AF
3 0x4041B6 в splev_
4 0x400BD0 в значении.3386 при pr.f90:?
5 0x400A6B в MAIN__ по адресу pr.f90:?
Ошибка сегментирования (сделан дамп памяти)
Если я скомпилирую свою программу с флагами -g -fbacktrace -fsanitize=address,zero,undefined
, появится следующее выходное сообщение:
QWE
0.37051690837706980
Программа получила сигнал SIGSEGV: ошибка сегментации — недопустимая ссылка на память.
Обратная трассировка для этой ошибки:
0 0x7FAB5F45CE08
1 0x7FAB5F45BF90
2 0x7FAB5EDA34AF
3 0x4075F0 в splev_ в splev.f:73 (дискриминатор 2)
4 0x400DDE в значении.3386 на pr.f90:87
5 0x400FFA в qwe.3406 на pr.f90:43
6 0x400F88 в версии 3403 на pr.f90:48
7 0x400D08 в MAIN__ на стр.f90:38
Ошибка сегментирования (сделан дамп памяти)
Если я скомпилирую свою программу с флагами -g -fbacktrace -Wall -fcheck=all
, появится следующее выходное сообщение:
QWE
Программа получила сигнал SIGSEGV: ошибка сегментации — недопустимая ссылка на память.
Обратная трассировка для этой ошибки:
0 0x7F2BE6F0FE08
1 0x7F2BE6F0EF90
2 0x7F2BE68564AF
3 0x4075F0 в splev_ в splev.f:73 (дискриминатор 2)
4 0x400DDE в значении.3386 на pr.f90:87
5 0x400C46 в MAIN__ на стр.f90:35
Ошибка сегментирования (сделан дамп памяти)
Если я скомпилирую свою программу с флагами -g -fbacktrace -fsanitize=address
, появится следующее выходное сообщение:
QWE
ASAN:SIGSEGV
=================================================================
==4796==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000408f67 bp 0x7ffe7a134440 sp 0x7ffe7a1341e0 T0)
0 0x408f66 in splev_ /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/splev.f:73
1 0x40145d in value.3386 (/home/yurchvlad/Science/Coll_Int/F90/f90DP/1/curfit 0x40145d)
2 0x4011a3 in intcoll /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/pr.f90:35
3 0x401849 in main /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/pr.f90:2
4 0x7fcad9b3282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x2082f)
5 0x400d38 in _start (/home/yurchvlad/Science/Coll_Int/F90/f90DP/1/curfit 0x400d38)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/splev.f:73 splev_
==4796==ABORTING
Firstly I will show the code and then I will give some information about subroutines CURFIT and SPLEV of library FITPACK which are playing there a principal role.
Here is my code. This is just a test program, i.e. it is not confusion, that I interpolate there array of values of analytical function.
PROGRAM IntColl
USE Constants
IMPLICIT NONE
INTEGER :: i, nen ! i = counter
! nen, nmn, ne is sirvice variables, which
! appear on exit of CURFIT and needed on entry
! of SPLEV and SPLINT
REAL(DP) :: foo
REAL(DP) :: MOM1 ! dimensionless neutrino momentum
REAL(DP) :: dmg ( 1 : 2 * NG) ! dimensionless momentum grid
REAL(DP) :: endf( 1 : 2 * NG) ! electron neutrino distribution function
! muon neutrino distribution function
! electron and positron distribution function
REAL(DP) :: ten ( 1 : 2 * NG k 1) ! service arrays:
! ten is array arising on exit of working of CURFIT
! and contain knots of the spline (for endf, mndf and edf correspondingly).
REAL(DP) :: cen ( 1 : 2 * NG k 1) ! needed on entry of SPLEV and SPLINT
! cen appear on exit of CURFIT, contain coefficients of spline
! (for endf, mndf and edf correspondingly) and needed on entry of SPLEV and SPLINT.
REAL(DP) :: w ( 1 : 2 * NG k 1) ! w is array of weights for points on entry of CURFIT.
DO i = 1, 2 * NG
dmg(i) = i / 10.D 00 ! filling arrays to give their
endf(i) = eq_nu_di_fu(dmg(i)) ! on entry into subroutine
w(i) = 1.d 00 ! CURFIT
END DO
MOM1 = .53D 00
PRINT *, 'QWE'
CALL spline(dmg, endf, nen, ten, cen)
foo = value(MOM1, ten, nen, cen)
PRINT *, foo
PRINT *, wer(MOM1)
CONTAINS
REAL(DP) FUNCTION qwe(q) ! qwe and wer is "wrappers" for using
REAL(DP) :: q ! of subroutines spline > curfit
qwe = value(q, ten, nen, cen) ! in main program
END FUNCTION qwe
REAL(DP) FUNCTION wer(q)
REAL(DP) :: q
wer = qwe(q)
END FUNCTION wer
SUBROUTINE spline(x, y, n, t, c) ! spline is "hand-made wrapper" for
IMPLICIT NONE ! more convenient using of subroutine
! CURFIT in main program
INTEGER :: m, nest, n, lwrk, ier
INTEGER, PARAMETER :: iopt = 0
INTEGER :: iwrk( 1 : 10 * NG )
REAL(DP) :: xb, xe, fp
REAL(DP) :: wrk( 1 : 2 * NG * (k 1) (2 * NG k 1) * (7 3 * k) )
REAL(DP) :: x( 1 : 2 * NG), y(1: 2 * NG )
REAL(DP) :: t( 1 : 2 * NG k 1 )
REAL(DP) :: c( 1 : 2 * NG k 1 )
xb = 0.d 00
xe = x(2 * NG)
m = 2 * NG
nest = m k 1
lwrk = 2 * NG * (k 1) nest * (7 3 * k)
CALL curfit(iopt, m, x, y, w, xb, xe, k, s, nest, n, t, c, fp, wrk, lwrk, iwrk, ier)
END SUBROUTINE spline
REAL(DP) FUNCTION value(q, t, n, c) ! value is "hand-made wrapper" for
IMPLICIT NONE ! more convenient using of subroutine
! SPLEV in main program
INTEGER :: n, ier ! SPLEV should work only after
INTEGER, PARAMETER :: m = 1 ! CURFIT edned its working
REAL(DP) :: q
REAL(DP) :: t( 1 : 2 * NG k 1 )
REAL(DP) :: c( 1 : 2 * NG k 1 )
REAL(DP) :: ddmg(1), sddmg(1)
ddmg(1) = q
CALL splev(t, n, c, k, ddmg, sddmg, m, ier)
value = sddmg(1)
END FUNCTION value
REAL(DP) FUNCTION eq_nu_di_fu(y) ! eq_nu_di_fy givev values for array
IMPLICIT NONE ! to interpolate
REAL(DP) :: y
eq_nu_di_fu = 1 / (EXP(y) 1)
END FUNCTION eq_nu_di_fu
END PROGRAM IntColl
Константы модуля есть:
MODULE CONSTANTS
INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(15, 307)
INTEGER, PARAMETER :: NG = 200 ! NUMBER OF KNOTS OF GRID
INTEGER , PARAMETER :: K = 3 ! THE ORDER OF SPLINE
REAL(DP), PARAMETER :: S = 0.D 00 ! CUBIC SPLINE SMOOTHING FACTOR
END MODULE
Теперь подпрограммы CURFIT и SPLEV, появляющиеся в приведенном выше коде со всеми их зависимостями, находятся в следующих источниках:
https://github.com/jbaayen/fitpackpp/tree/master/fitpack
где эти подпрограммы имеют двойную точность
и
http://www.netlib.org/dierckx/
где эти подпрограммы имеют одинарную точность.
Очень важно упомянуть, что с одинарной точностью вышеуказанная схема работает!
Конечно, если я использую подпрограммы одинарной точности, я соответствующим образом изменяю все типы всех переменных.
Что еще я наблюдал:
-
прямое использование значения ФУНКЦИИ работает.
-
Если строка PRINT *, ‘QWE’ основной программы прокомментирована, значение ‘foo’ также не печатается.
Комментарии:
1. Используйте проверки компилятора для выявления ошибок. Вы можете найти многие сами. Попробуйте:
gfortran -g -fbacktrace -Wall -fcheck=all
а такжеgfortran -g -fbacktrace -fsanitize=address,zero,undefined
. Скомпилируйте свой код с этими параметрами, повторно запустите его и сообщите о результатах.2. @Vladimir F
-g -fbacktrace -Wall -fcheck=all
возвращаетfpcurf.f:186:35: if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp) 1 Warning: Possible change of value in conversion from REAL(8) to INTEGER(4) at (1) [-Wconversion]
и-g -fbacktrace -fsanitize=address,zero,undefined
возвращаетgfortran: error: unrecognized argument to -fsanitize= option: ‘zero’
3. Что произойдет, если вы запустите программу, скомпилированную с этими флагами?
4. @Ian Bush если я запускаю программу, скомпилированную с этими флагами, возвращается тот же результат
5. Я серьезно сомневаюсь, что результат был точно одинаковым, в обратном пути должны быть, по крайней мере, номера строк. Попробуйте удалить «ноль» из флага очистки. При необходимости удалите также «неопределенный» и перезапустите.