FORTRAN 中的 "segmentation fault - invalid memory reference error" 是什么

what is "segmentation fault - invalid memory reference error" in FORTRAN

我在 Fortran 代码中收到以下错误:

  Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

  Backtrace for this error:
  #0  0x7F80C7B46777
  #1  0x7F80C7B46D7E
  #2  0x7F80C7282D3F
  #3  0x402D1A in __mymodule_MOD_gcr_mfree
  #4  0x412175 in MAIN__ at HUHSI1.f90:?
  Segmentation fault (core dumped)
  ------------------
  (program exited with code: 139)
  1. 我完全不明白这个错误。这是什么错误?

    数字 3 表示以下子程序:

    SUBROUTINE gcr_Mfree(F2,Cnew,Cold,C_Fold,xm,converged)
    
        !**** FUNCTIONS TO BE SOLVED ****
        ! Generalized Conjugate Residual Algorithm
        ! Solves M*x=b (J*dx=-F)
    
        IMPLICIT REAL*8 (A-H,O-Z)
    
        INTEGER, intent(out)                :: converged  
        REAL*8, DIMENSION(:,:), ALLOCATABLE :: F2,p,Mp             
        REAL*8, DIMENSION(:),   ALLOCATABLE :: F2V,F22V,CnewV,ColdV,C_FoldV,alpha2,r,b,Mr,xv
    
        ! 2D INPUT VARIABLE DIMENSIONS:
        DIMENSION F22(-2:IG+2,-2:JG+2)
        DIMENSION Cnew(-2:IG+2,-2:JG+2)
        DIMENSION Cold(-2:IG+2,-2:JG+2)
        DIMENSION C_Fold(-2:IG+2,-2:JG+2)
        DIMENSION xm(-2:IG+2,-2:JG+2)
    
        integer :: j,maxiter,iter
        real*8 :: tol,normr  
        !===================================================================           
    
        MASK = SIZE(F2)                 ! Size of F2 : (IG+5)*(JG+5)
        Print*, 'MASK IS EQUAL TO',MASK
        ALLOCATE(F2V(1:MASK))
        ALLOCATE(CnewV(1:MASK))
        ALLOCATE(ColdV(1:MASK))
        ALLOCATE(C_FoldV(1:MASK))
        ALLOCATE(xv(1:MASK))
    
        ALLOCATE(r(1:MASK))
        ALLOCATE(b(1:MASK))
        ALLOCATE(p(1:IG,1:JG))
        ALLOCATE(Mp(1:IG,1:JG))
    
        !************* RESHAPING MATRICES TO VECTORS **************
        F2V     = RESHAPE(F2    ,(/MASK/))
        ColdV   = RESHAPE(Cold  ,(/MASK/))
        CnewV   = RESHAPE(Cnew  ,(/MASK/))
        C_FoldV = RESHAPE(C_Fold,(/MASK/))
    
       !            Write(*,*) shape(CnewV), shape(Cnew)
       !            WRITE(*,*) 'Cold='
       !            WRITE(*,554) Cold
       !            WRITE(*,*) 'Cnew='
       !            WRITE(*,554) Cnew
       !554         FORMAT(F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F4.2,1X,F5.3,1X,F5.3,1X)     
    
        b       = -F2V(1:MASK)                !(why minus?)
    
        tol     = 5.E-2
        alpha2  = 1e-6 
        maxiter = MASK
        r       = b(1:MASK)               ! we need this when calculating r_new
        normr    = sqrt(sum( r(:)**2 ))                  !!!! Norm               
    
        557         FORMAT(1X,F5.2,2X,F5.2,10X,F5.2,4X,F5.2,10X,F5.2,2X,F5.2)
        WRITE(*,*) 'ColdV,CnewV'
        WRITE(*,557) ColdV,CnewV,F2V,C_FoldV,b,r
        PRINT*, 'normr=', nomr
    
        !************* MAIN CALCULATION ****************
        DO iter=1,maxiter
    
            !Get preliminary search direction
            p(:,iter) = r(:)
    
                            WRITE(*,*) 'p='
                            WRITE(*,558) ,p
            558             FORMAT(1X,F4.2) 
    
            ! Approximate the Jacobian(M) residual product
            CnewV = CnewV + alpha2 * r
    
            WRITE(*,*), 'CnewV='
            WRITE(*,559) ,CnewV
            559             FORMAT(1X,F4.2)
    
            Cnew = RESHAPE(CnewV,(/IG+5,JG+5/))                 
    
            !********** Call Crank-Nicolson Function               
    
            F22V= RESHAPE(F22,(/MASK/))
    
            Mr(:) = (1/alpha2)*(F22V-F2V)      !GUIDE: (The apporximated Jacobian matrix)
    
            Mp(:,iter) = Mr(:)
    
            !! Orthogonalize search direction
            do j = 1, iter-1
                p(:,iter)  = p(:,iter)  - sum( Mp(:,j) * Mp(:,iter) ) * p(:,j)
                Mp(:,iter) = Mp(:,iter) - sum( Mp(:,j) * Mp(:,iter) ) * Mp(:,j)
            enddo
    
            !Normalize search direction              
            p(:,iter)  =  p(:,iter) / (norm2(Mp(:,iter))) 
            Mp(:,iter) = Mp(:,iter) / (norm2(Mp(:,iter)))
    
            !Update solution and residual
            alpha2 = sum( r(:) * Mp(:,iter) ) / sum( Mp(:,iter)**2 )                            
            xv = xv + alpha2 * p(:,iter)
            r = r - alpha2 * Mp(:,iter)      ! where is the *(Cnew - C)?
    
            xm = RESHAPE(xv,(/IG+5,JG+5/)) 
    
            !Check convergence
            normr=sqrt(sum( r(:)**2 ))                               !!!! norm
            !fprintf('norm(r) = !g iter = !gNewLine',normr,iter+1);
            if (normr.LT.tol) then
                converged=1
                exit
            end if
    
    
        END DO 
    
        if (normr > tol) then
            write(*,*) 'GCR SOLUTION DID NOT CONVERGE!'
            converged=0
        end if
    
        RETURN
    END subroutine gcr_Mfree
    

    为了找出我收到此错误的原因,我做了几件事:

    我已经通过逐步打印来跟踪代码中变量的值。我已经达到了这个公式,我无法再打印 CnewV 的值。

    CnewV = CnewV + alpha2 * r
    
  2. 这个公式在"mymodule_MOD_gcr_mfree"中,在错误信息中用#3表示。 为什么错误不指示任何行号?

    "r" 是一个向量。 "alpha2" 是标量。 RHS 处的 CnewV 是向量。 "r"和"CnewV"的大小和秩相同,"CnewV"向量中只有一个元素的值为NaN。此外,当我尝试在屏幕上打印时,两个或三个元素被打印为“*****”。

  3. 打印矩阵"p"(格式编号为558)时,数组p中的元素少了很多。数组"r"中有221个元素,而"p"

  4. 中有96个

这是一个复杂的问题。我希望给定的信息足以理解错误。

您在 pMp 上都超出了数组边界,它们的维度都是 (1:IG,1:JG)。 iter 的外部循环从 1 运行到 maxiter=MASK=(IG+5)*(JG+5),最终导致 p(:,iter) 的非法内存访问。还有行

p(:,iter)=r(:)

不匹配,因为 r 有 size=MASK。

问题 1 的答案: 分段错误是由于内存冲突。在这种情况下,错误是由于变量分配错误而产生的。另外,我们应该设置变量限制。

错误:

CnewV = CnewV + alpha2 * r

更正:

CnewV(0:IG,0:JG) = CnewV(0:IG,0:JG) + alpha2 * r(0:IG,0:JG)

问题 2 的答案: 我相信这是一个编译器错误。我也检查了其他编译​​器,none 能够解决此类错误。

问题 3 的答案: function/subroutine 中的数组元素数量少是由于调用 function/subroutine 期间变量设置不当造成的。如果出现此错误,您应该将该变量添加到应该调用的变量列表中。

指针赋值仍然不能正常工作: 我设法克服了分段错误,整个代码编译得很好。但是,我在第 3 次迭代后收到 NaN 数字。

下面的测试代码旨在显示问题的根源。我尝试了以下解决方案。但是,我无法在每次迭代时将向量 'Mr' 写入目标矩阵 'Mp' 的列!

 program ptrtest

 real, pointer, CONTIGUOUS :: Mr(:)
 real, pointer, CONTIGUOUS :: Mp(:,:)
 real, DIMENSION(9) ::abc


 integer :: n = 2
 iter=3

 Do i=1,iter

 alpha2 = 2
 allocate(Mr(n**2))
 abc= 42

 Mr(1:n**2) = 0.5 * abc(1:n**2)
 write(*,*) 'Mr='
 write(*,555) Mr

 Mr(1:n**2) => Mp(1:n**2,1:1) 

 WRITE(*,*) 'Mp='
 WRITE(*,555) Mp

 end do

 555  FORMAT(F12.4,1X) 


 end program ptrtest

错误:

 gfortran -Wall -fcheck=all "Pointer.f95" (in directory: /home/vahid/Dropbox/To Move folder/Geany/Test_Pointer application)
 Pointer.f95:25.3:
 Mr(1:n**2) => Mp(1:n**2,1:i)
 1
 Error: Incompatible ranks 1 and 2 in assignment at (1)
 Compilation failed.

我试过了Mp(1:n**2,1:i) => Mr(1:n**2)。这克服了编译错误。然而,Mp 不是目标,向量的元素在每次迭代时被重写到矩阵的第一列。