为什么在调用子例程中逐渐嵌套在两个具有双精度的函数中的子例程中,fortran中会出现分段错误?

时间:2019-03-26 17:55:07

标签: fortran gfortran

我尝试通过嵌套在另一个函数(下面的代码)中的两个函数(“ wer”和“ qwe”)来调用FITPACK库的子例程SPLEV。

在已编译程序的执行中会出现以下消息:

  

QWE

     

程序接收到的信号SIGSEGV:分段错误-无效的内存引用。

     

此错误的回溯:

     

0 0x7F3EE4BF3E08

     

1 0x7F3EE4BF2F90

     

2 0x7F3EE453A4AF

     

3 0x4041B6 in splev _

     

值为4 0x400BD0.f90时为3386:?

     

在MAIN__中的5 0x400A6B在pr.f90:?

     

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

如果我使用标志-g -fbacktrace -fsanitize=address,zero,undefined编译程序,则会显示以下输出消息:

  

QWE

     

0.37051690837706980

     

程序接收到的信号SIGSEGV:分段错误-无效的内存引用。

     

此错误的回溯:

     

0 0x7FAB5F45CE08

     

1 0x7FAB5F45BF90

     

2 0x7FAB5EDA34AF

     

splev_中的3 0x4075F0在splev.f:73(判别器2)

     

4 0x400DDE value.3386在pr.f90:87

     

qwe.3406中的5 0x400FFA在pr.f90:43

     

在wer.3403中的6 0x400F88在f.90:48

     

在MAIN__中的7 0x400D08在pr.f90:38

     

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

如果我使用标志-g -fbacktrace -Wall -fcheck=all编译程序,则会显示以下输出消息:

  

QWE

     

程序接收到的信号SIGSEGV:分段错误-无效的内存引用。

     

此错误的回溯:

     

0 0x7F2BE6F0FE08

     

1 0x7F2BE6F0EF90

     

2 0x7F2BE68564AF

     

splev_中的3 0x4075F0在splev.f:73(判别器2)

     

4 0x400DDE value.3386在pr.f90:87

     

在MAIN__中的5 0x400C46在f.90:35

     

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

如果我使用标志-g -fbacktrace -fsanitize=address编译程序,则会显示以下输出消息:

  

QWE

     

ASAN:SIGSEGV

     

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

     

== 4796 ==错误:AddressSanitizer:未知地址上的SEGV 0x000000000000(PC 0x000000408f67 bp 0x7ffe7a134440 sp 0x7ffe7a1341e0 T0)

     

splev_ /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/splev.f:0 0x408f66: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

     

主/home/yurchvlad/Science/Coll_Int/F90/f90DP/1/pr.f90:2中的3 0x401849

     

__ libc_start_main中的4个0x7fcad9b3282f(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

     

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

     

AddressSanitizer无法提供其他信息。

     

摘要:地址消毒剂:SEGV /home/yurchvlad/Science/Coll_Int/F90/f90DP/1/splev.f:73 splev _

     

== 4796 ==正在终止

首先,我将显示代码,然后提供有关库FITPACK的子例程CURFIT和SPLEV的一些信息,这些子例程在其中起主要作用。

这是我的代码。这只是一个测试程序,也就是说,我可以在其中插入解析函数的值数组,这不是混乱。

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. 如果行 打印*,'QWE' 在主程序的注释中,也不会显示值'foo'。

0 个答案:

没有答案