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)
我完全不明白这个错误。这是什么错误?
数字 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
这个公式在"mymodule_MOD_gcr_mfree"中,在错误信息中用#3表示。 为什么错误不指示任何行号?
"r" 是一个向量。 "alpha2" 是标量。 RHS 处的 CnewV 是向量。 "r"和"CnewV"的大小和秩相同,"CnewV"向量中只有一个元素的值为NaN。此外,当我尝试在屏幕上打印时,两个或三个元素被打印为“*****”。
打印矩阵"p"(格式编号为558)时,数组p中的元素少了很多。数组"r"中有221个元素,而"p"
中有96个
这是一个复杂的问题。我希望给定的信息足以理解错误。
您在 p
和 Mp
上都超出了数组边界,它们的维度都是 (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 不是目标,向量的元素在每次迭代时被重写到矩阵的第一列。
我在 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)
我完全不明白这个错误。这是什么错误?
数字 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
这个公式在"mymodule_MOD_gcr_mfree"中,在错误信息中用#3表示。 为什么错误不指示任何行号?
"r" 是一个向量。 "alpha2" 是标量。 RHS 处的 CnewV 是向量。 "r"和"CnewV"的大小和秩相同,"CnewV"向量中只有一个元素的值为NaN。此外,当我尝试在屏幕上打印时,两个或三个元素被打印为“*****”。
打印矩阵"p"(格式编号为558)时,数组p中的元素少了很多。数组"r"中有221个元素,而"p"
中有96个
这是一个复杂的问题。我希望给定的信息足以理解错误。
您在 p
和 Mp
上都超出了数组边界,它们的维度都是 (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 不是目标,向量的元素在每次迭代时被重写到矩阵的第一列。