Почему ошибка сегментации возникает в фортране при вызове подпрограммы, постепенно вложенной в две функции с двойной точностью? - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь вызвать подпрограмму SPLEV библиотеки FITPACK через две функции ('wer' и 'qwe'), вложенные одна в другую (код ниже).

При выполнении скомпилированной программы появляется следующее сообщение:

QWE

Программа получила сигнал SIGSEGV: Ошибка сегментации - недопустимая ссылка на память.

Backtrace для этой ошибки:

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: Ошибка сегментации - недопустимая ссылка на память.

Backtrace для этой ошибки:

0 0x7FAB5F45CE08

1 0x7FAB5F45BF90

2 0x7FAB5EDA34AF

3 0x4075F0 в splev_ на splev.f: 73 (дискриминатор 2)

4 0x400DDE в значении.3386 по pr.f90: 87

5 0x400FFA в кв.3406 по pr.f90: 43

6 0x400F88 в wer.3403 по pr.f90: 48

7 0x400D08 в MAIN__ на pr.f90: 38

Ошибка сегментирования (сделан дамп памяти)

Если я скомпилирую свою программу с флагами -g -fbacktrace -Wall -fcheck=all, появится следующее сообщение:

QWE

Программа получила сигнал SIGSEGV: Ошибка сегментации - недопустимая ссылка на память.

Backtrace для этой ошибки:

0 0x7F2BE6F0FE08

1 0x7F2BE6F0EF90

2 0x7F2BE68564AF

3 0x4075F0 в splev_ на splev.f: 73 (дискриминатор 2)

4 0x400DDE в значении.3386 по pr.f90: 87

5 0x400C46 в MAIN__ на pr.f90: 35

Ошибка сегментирования (сделан дамп памяти)

Если я скомпилирую свою программу с флагами -g -fbacktrace -fsanitize=address, появится следующее сообщение:

QWE

АСАН: SIGSEGV

=============================================== ==================

== 4796 == ОШИБКА: AddressSanitizer: SEGV по неизвестному адресу 0x000000000000 (шт 0x000000408f67 п.о. 0x7ffe7a134440 sp 0x7ffe7a1341e0 T0)

0 0x408f66 в splev_ /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/splev.f:73

1 0x40145d в значении.3386 (/ home / yurchvlad / Science / Coll_Int / F90 / f90DP / 1 / curfit + 0x40145d)

2 0x4011a3 в intcoll /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/pr.f90:35

3 0x401849 в главном /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/pr.f90:2

4 0x7fcad9b3282f в __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

5 0x400d38 в _start (/ home / yurchvlad / Science / Coll_Int / F90 / f90DP / 1 / curfit + 0x400d38)

AddressSanitizer не может предоставить дополнительную информацию.

РЕЗЮМЕ: AddressSanitizer: SEGV /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/splev.f:73 splev_

== 4796 == ABORTING

Сначала я покажу код, а затем предоставлю некоторую информацию о подпрограммах CURFIT и SPLEV библиотеки FITPACK, которые играют там главную роль.

Вот мой код. Это всего лишь тестовая программа, то есть не путать, что я интерполирую туда массив значений аналитической функции.

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/

где эти подпрограммы с одинарной точностью.

ЭтоОчень важно отметить, что приведенная выше схема с одинарной точностью работает!

Конечно, если я использую подпрограммы одинарной точности, я изменяю все типы всех переменных соответствующим образом.

Что еще у меня есть?наблюдается:

  1. прямое использование значения FUNCTION работает.

  2. Если закомментирована строка PRINT *, 'QWE' основной программы,значение 'foo' также не печатается.

...