Fortran f90中的内存损坏
我有以下代码Fortran f90中的内存损坏,fortran,gfortran,memory-corruption,Fortran,Gfortran,Memory Corruption,我有以下代码 PROGRAM CTS implicit none !C driver for routine fourn INTEGER NDAT,NDIM PARAMETER(NDIM=1,NDAT=1024) INTEGER i,idum,isign,j,k,l,nn(NDIM) REAL data1(NDAT),data2(NDAT),ran1 ,x,dx REAL,DIMENSION(:),
PROGRAM CTS
implicit none
!C driver for routine fourn
INTEGER NDAT,NDIM
PARAMETER(NDIM=1,NDAT=1024)
INTEGER i,idum,isign,j,k,l,nn(NDIM)
REAL data1(NDAT),data2(NDAT),ran1 ,x,dx
REAL,DIMENSION(:),ALLOCATABLE::F,F1
allocate(F(NDAT),F1(NDAT))
x=1.
dx = (200.-1.)/real(NDAT)
nn(1)=NDAT
do i=1,NDAT
F1(i) =atan(x-100)
x= x + dx
enddo
x=1.
x=1.
isign=1
call fo(F1,nn,1,isign)
open(1,file="zresult.dat",status="replace")
do i=1,NDAT
write(1,*)x,F1(i)*dx
x= x + dx
enddo
stop
END
!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE fo(data,nn,ndim,isign)
INTEGER isign,ndim,nn(ndim)
REAL data(*)
INTEGER i1,i2,i2rev,i3,i3rev,ibit,idim,ifp1,ifp2,ip1,ip2,ip3,k1,&
k2,n,nprev,nrem,ntot
REAL tempi,tempr
DOUBLE PRECISION theta,wi,wpi,wpr,wr,wtemp
ntot=1
do 11 idim=1,ndim
ntot=ntot*nn(idim)
11 continue
nprev=1
do 18 idim=1,ndim
n=nn(idim)
nrem=ntot/(n*nprev)
ip1=2*nprev
ip2=ip1*n
ip3=ip2*nrem
i2rev=1
do 14 i2=1,ip2,ip1
if(i2.lt.i2rev)then
do 13 i1=i2,i2+ip1-2,2
do 12 i3=i1,ip3,ip2
i3rev=i2rev+i3-i2
tempr=data(i3)
tempi=data(i3+1)
data(i3)=data(i3rev)
data(i3+1)=data(i3rev+1)
data(i3rev)=tempr
data(i3rev+1)=tempi
12 continue
13 continue
endif
ibit=ip2/2
1 if ((ibit.ge.ip1).and.(i2rev.gt.ibit)) then
i2rev=i2rev-ibit
ibit=ibit/2
goto 1
endif
i2rev=i2rev+ibit
14 continue
ifp1=ip1
2 if(ifp1.lt.ip2)then
ifp2=2*ifp1
theta=isign*6.28318530717959d0/(ifp2/ip1)
wpr=-2.d0*sin(0.5d0*theta)**2
wpi=sin(theta)
wr=1.d0
wi=0.d0
do 17 i3=1,ifp1,ip1
do 16 i1=i3,i3+ip1-2,2
do 15 i2=i1,ip3,ifp2
k1=i2
k2=k1+ifp1
tempr=sngl(wr)*data(k2)-sngl(wi)*data(k2+1)
tempi=sngl(wr)*data(k2+1)+sngl(wi)*data(k2)
data(k2)=data(k1)-tempr
data(k2+1)=data(k1+1)-tempi
data(k1)=data(k1)+tempr
data(k1+1)=data(k1+1)+tempi
15 continue
16 continue
wtemp=wr
wr=wr*wpr-wi*wpi+wr
wi=wi*wpr+wtemp*wpi+wi
17 continue
ifp1=ifp2
goto 2
endif
nprev=n*nprev
18 continue
return
END
!!!!!!!!!!!
问题是,如果我不分配F1
并将REAL F1(NDAT)
放入,代码运行时不会出现任何问题,但是当我分配F1
时,我将得到以下错误
我已经尝试了所有的可能性去理解正在发生的事情。这似乎是内存损坏
*** Error in `./out': free(): invalid next size (normal): 0x088a7f20 ***
Program received signal SIGABRT: Process abort signal.
Backtrace for this error:
#0 0xB76BE133
#1 0xB76BE7D0
#2 0xB77C73FF
#3 0xB77C7424
#4 0xB74E4686
#5 0xB74E7AB2
#6 0xB751EFD2
#7 0xB75294C9
#8 0xB752A13C
#9 0xB7777607
#10 0xB776EECF
#11 0xB776EFB9
#12 0xB76BDA93
#13 0xB77D733B
#14 0xB74E9230
#15 0xB74E928C
#16 0xB76C09E7
#17 0x80496D4 in cts at z2.f90:33
Aborted (core dumped)
你能帮我找出问题出在哪里吗。
非常感谢如果将
结束
移动到子例程之后,将包含
放在子例程之前,使其成为程序内部,请更改假定大小数组
data(*)
假设形状阵列
data(:)
(仅使用数据(NDAT)
也会有所帮助)
然后您可以将代码编译为
gfortran-7 -Wall -Wno-unused-variable -fcheck=all memcorr.f90
并得到明确的信息
> ./a.out
At line 63 of file memcorr.f90
Fortran runtime error: Index '1025' of dimension 1 of array 'data' above upper bound of 1024
这意味着您正在访问超出边界的阵列。
第63行是:
data(i3)=data(i3rev)
因此i3
或i3rev
太大(大于NDAT
)。你必须找出原因并解决这个问题
要点是:使用显式接口、假定形状数组和所有其他Fortran 90的东西来帮助您查找bug
最好是为所有子例程和函数使用模块。如果其他人应该理解,请使用更好的代码格式。你的缩进很可怕,而且完全不一致。我相信它可以缩短很多(请参阅)。@High-Performance Mark能否请您进一步解释如何使用stat?
allocate(…,stat=integer\u variable)
,但这对您没有帮助。错误不会因分配而发生,也不会在分配过程中发生。请看答案。Q Vladimir F但为什么它不会发生在我放F(数据)的时候,并且只有当我分配F1时它才会发生???它总是发生,请看下面我的答案。非常感谢你,但是为什么它不会发生在我放F(数据)的时候,只有当我分配F1时它才会发生???你的错误总是发生。你只是有时候没注意到。错误程序未定义。它可以做任何事情。请参见本例,这取决于操作系统如何分配内存以及在何处存储信息的详细信息。现在不值得挖掘细节,这对你的水平来说太复杂了。请记住,内存损坏会导致不可预测的错误,这些错误可能会随机更改。那么,如果我向子例程发送指针,问题应该得到解决吗?