Arrays “什么是”呢;分段故障-无效内存引用错误“;用FORTRAN语言
我在Fortran代码中收到以下错误:Arrays “什么是”呢;分段故障-无效内存引用错误“;用FORTRAN语言,arrays,fortran,fortran90,segmentation-fault,Arrays,Fortran,Fortran90,Segmentation Fault,我在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 0x41217
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)
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
这是一个复杂的问题。我希望给出的信息足以理解错误。您在
p
和Mp
上都超出了数组界限,这两个数组都是维度(1:IG,1:JG)
。iter的外环从1运行到maxiter=MASK=(IG+5)*(JG+5)
,最终导致p(:,iter)
的非法内存访问。还有那条线
p(:,iter)=r(:)
是不匹配的,因为
r
具有大小=掩码 问题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不是目标,每次迭代时向量的元素都会被重写到矩阵的第1列。将“隐式实数*8(A-H,O-Z)”替换为“隐式无”并显式声明所有变量应该是有用的。这也有助于打开编译器选项进行运行时非法下标检查。e、 例如,在gfortran中,使用-fcheck=bounds
或-fcheck=all
@Vahid no,NaN是一个有效的浮点值,如果它将导致错误(取决于一些事情),它将是一个浮点信号,您将得到不同的错误。SIGSEGV aka signal 11是一个通用的“您试图访问不允许访问的内存”错误。它可能由双重释放、缓冲区溢出等引起。您的所有分配都成功了吗?你不是在检查。。。还可以尝试将-g-fbacktrace
(如果使用gfortran)或-g-traceback
(如果使用ifort)添加到编译命令中,以获得调试符号,并希望在执行SEGFAULT时获得更多信息除了我的答案之外,您真的想为潜在存储IG*JG迭代提供空间吗?如果你超过了几百点,这看起来就像它会爆炸一样可怕。如果只是一个小问题,那就不要理会。在你的代码中搜索编译器很容易识别的bug是浪费你和每个人的时间。使用gfortran-g3-fcheck=all-Wall-fbacktrace编译。如果您使用的gfortran版本足够新,请添加-fsanitize=undefined-fsanitize=address-fsanitize=leak
。请仔细阅读编译器手册。其他编译器的编译器中也有类似的标志。谢谢您的提醒。其思想是将向量“r”存储到矩阵p的列中。向量“r”在每次迭代时都会更新。Hi@Vahid,添加的代码显示Mr(1:n**2)=>Mp(1:n**2,1:1)
,而错误消息显示Mr(1:n**2)=Mp(1:n**2,1:i)
。你想说什么?(后者不在添加的代码中…)是否要创建指向Mp(:,:)的第i列的数组指针?此外,由于Mp未分配,因此先生无法指向它!我觉得您可能对Fortran数组(指针)和Matlab数组有混合的理解。在Matlab数组中,我们可以执行Mp(1:n**2,i)=Mr(1:n**2)
,即使之前没有定义左侧。另一方面,在迭代开始之前,Fortran数组必须分配为allocate(Mp(1:n**2,1:Niter))
。然后在迭代中执行Mp(1:n**2,i)=Mr(1:n**2)
。换句话说,Matlab的数组可以根据需要自动增大大小,而Fortran的数组则不能。即使使用数组指针,这一事实也不会改变(细节被省略…@roygvib解释:我想在循环中将一个1D数组强制转换为2D数组的列。在第一次迭代时,该二维阵列的大小与1D阵列的大小相同。所以投下它应该没有问题。在第二次迭代中,1D数组将有不同的元素。我想把它转换到2D数组的第二列。这