繁体   English   中英

什么是 FORTRAN 中的“分段错误 - 无效的内存引用错误”

[英]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 (AH,OZ) 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”中有 96 个元素

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

您超出了尺寸为(1:IG,1:JG) pMp的数组边界。 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 的答案:我相信这是一个编译器错误。 我也检查了其他编译​​器,但没有一个能够解决这种类型的错误。

问题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 不是目标,并且每次迭代时向量的元素都被重写到矩阵的第一列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM