我有一个似乎正常运行的程序, 但我不知道怎么可能 因为似乎有一个明显的错误。
主程序(使用“隐式”)调用一个子例程:
implicit integer(i-n)
implicit double precision(a-h,o-y)
implicit complex*16(z)
call do_coulomb(zvecs0,zdualvecs0,n_f,n_f,1,
$ nsubfilling,zcorrmatrix,0,aldet01abs,
$ zcoulomb,epsilon)
其中声明了数组'zvecs0','zdualvecs0','zcorrmatrix',
但是任何地方都没有声明“ nsubfilling”。
(可能是旧版本的错误或残缺。)
因为我找不到
主程序中数组“ nsubfilling”的任何声明
('grep -i nsubfilling *'),
我想“ nsubfilling”将被视为整数变量。
这是一个问题子程序:
subroutine do_coulomb(zvecs,zdualvecs,n_A,n_Ap,n_C,
$ nsubfilling,zcorrmatrix,n1_p0,aldet01abs,
$ zcoulomb,eps)
implicit integer(i-n)
implicit double precision(a-h,o-y)
implicit complex*16(z)
include "input.inc"
dimension zvecs(0:L-1,0:L-1,0:L-1,0:Lt,0:1,0:1,0:n_f-1)
dimension zdualvecs(0:L-1,0:L-1,0:L-1,0:Lt,0:1,0:1,0:n_f-1)
dimension nsubfilling(0:n_Ap-1,0:n_C-1)
dimension zcorrmatrix(0:n_Ap-1,0:n_Ap-1)
(“ L”“ Lt”在“ input.inc”文件中定义。)
由于“ nsubfilling”在子例程中定义为数组,
我以为主程序和子程序之间的不匹配会导致错误。
但是,即使不匹配,该程序也可以正常运行。
我试图打印出一些变量。('n_f'= 4,'n_c'= 1) 这是输出:
Before 1st call in main:
nsubfilling= 1
zcorrmatrix(0,0)= (20.510951695209510,0.13579118691198364)
zcorrmatrix(0,1)= (-1.0490102491588316,0.59453967445518319)
zcorrmatrix(1,0)= (-1.3791781667351797,-0.26247624491732802)
zcorrmatrix(n_f-1,n_f-1)= (20.510951695209513,-0.13579118691198364)
Inside do_coulomb subroutine:
nsubfilling= 1 0 1 1
zcorrmatrix(0,0)= (20.510951695209510,0.13579118691198364)
zcorrmatrix(0,1)= (-1.0490102491588316,0.59453967445518319)
zcorrmatrix(1,0)= (-1.3791781667351797,-0.26247624491732802)
zcorrmatrix(n_f-1,n_f-1)= (20.510951695209513,-0.13579118691198364)
n1p0= 0
After 1st call in main:
nsubfilling= 1
zcorrmatrix(0,0)= (20.510951695209510,0.13579118691198364)
zcorrmatrix(0,1)= (-1.0490102491588316,0.59453967445518319)
zcorrmatrix(1,0)= (-1.3791781667351797,-0.26247624491732802)
zcorrmatrix(n_f-1,n_f-1)= (20.510951695209513,-0.13579118691198364)
输出显示'nsubfilling'在主例程中被视为整数, 但在子程序中也被视为数组 子例程正确识别“ zcorrmatrix” 即使不匹配。
但是,这怎么可能呢?我认为应该有一个错误。
您能让我了解它的工作原理吗?
谢谢。
答案 0 :(得分:1)
主程序没有子程序do_coulomb
的显式接口。这意味着主程序无法在编译时检查主程序中实际参数的等级是否与子例程中的虚拟参数的等级相匹配。
可以通过多种方式提供显式接口:
具有子例程do_coulomb
作为主程序的内部子程序(在主子程序之后,在CONTAINS
语句之后和在主程序的END
语句之前的子例程),这称为主机关联;
(提供子例程的名称,伪参数列表,它们的类型和属性);或
通过将子例程包含在模块(foo
)内,并在隐式声明之前添加use语句(use module foo
),这称为use association。
为什么您的程序不会崩溃?好吧,因为子例程do_coulomb
认为自己可以访问与子例程内部指定的大小nsubfilling
相对应的内存块,并且在操作该子例程时它不会做任何其他非法的事情-内存恰好被同一应用程序使用。如果nsubfilling
的声明大小非常大,并且/或者您声明的数组较少,则对nsubfilling
的访问很可能导致分段错误。
请注意,即使您具有显式接口,等级和尺寸也可能不匹配-只要子程序中dummy参数的总大小不大于的总大小,这可能是合法的主程序中的实际参数。