2011-10-04 137 views
1

我试图编译我的程序与英特尔Fortran编译器Linux(版本12.0.3)和我得到这个错误:Fortran编译错误

buggy.f90(206): error #6219: A specification expression object must be a dummy 
argument, a COMMON block object, or an object accessible through host or use 
association [SPECTRUM] 
    type(spect)      :: spectrum 
----------------------------------------^ 

这是一个模块内。 type(spect)来自另一个模块,其中我use在一开始的麻烦模块。这是一些代码;更多细节可以在下面找到。

module non_buggy 

    implicit none 

    type axis 
     character(len=6) :: nucleus 
     integer   :: num_data_points 
     real    :: spectral_width 
    end type axis 

    type spect 
     integer     :: num_dim 
     type(axis), allocatable :: axes(:) 
     real, allocatable  :: intensity(:) 
     character(len=10)  :: type = '' 
    end type spect 

    type(spect), target :: spectrum ! might this be a cause of error? 

    contains 
    ! ... 
end module non_buggy 


module buggy 

    use non_buggy 

    implicit none 

    contains 

    subroutine no_problem_here() 

     type(spect) :: spectrum ! compiles beautifully 
     ! ... 
    end subroutine no_problem_here 

    subroutine problem() 
     type(spect) :: spectrum ! does not compile, but no error if I change the variable name 
     ! ... 
    end subroutine problem 
end module buggy 

我看了一下是什么错误意味着,但我有什么,我在我的代码正在做的,不适用的印象 - 没有数组边界是在这些线路中指定。由于错误消失了,如果我将第二次出现的spectrum重命名为其他内容,我想知道该问题是否与模块non_buggy中的模块变量spectrum有关(但是,即使我注释掉该行,错误仍然存​​在其中声明了模块变量)。如果Fortran专家能够澄清这个问题,我将非常感激。

非常感谢!

+1

该错误是在别的地方。我甚至尝试编译你的模块。但我相信问题的根源在别的地方。因为你分享代码的和平没有任何问题。如果可能,请更多代码。 – Wildcat

+0

@kemiisto你是对的!我发现这个问题,它在编译器指出的线下面三行。我确实在数组边界声明中使用了'频谱'的一部分 - 当然,编译时没有指定大小... – canavanin

回答

2

在代码示例中,我看不到任何错误,即使它很容易出错(例如,在例程no_problem_here和问题中)声明具有与全局变量相同名称(频谱)的局部变量模块non_buggy)。

你使用什么编译器?我用ifort 11.1和gfortran 4.7.0编写了样例,没有任何问题(只是在注释模块non_buggy的关键字CONTAINS时,因为ifort抱怨在“contains”和“end module”之间没有指令)。

+0

感谢您的时间和精力!我发现了这个问题;它与模块变量名称相同的局部变量无关,它只是我有点愚蠢......(请参阅原始问题下的我的评论) – canavanin

4

无法在linux和osx上使用ifort 11进行重现。我没有ifort 12,所以我无法验证,但这里的要点是,您要从模块中导出spectrum,这很可能是个坏主意。请务必在模块中使用关键字private,并明确公开您想要发布的内容。

如果你想让光谱成为一个模块变量(我不明白,为什么你会?你期望一个且只有一个光谱?你确定吗?)你也可以考虑如果你需要一个save关键字来保存这些值。

最后,你掩盖了一个模块变量。 Idiotic Fortran没有命名空间的概念。如果你从另一个模块中的某个模块中摧毁了所有的东西,就会污染你的命名空间,而且你很可能最终会遇到这些情况。在某些情况下支持子程序导入,以限制损害(尽管它变得不太通信)。保持你的模块的最小值,当你这样做的时候,要么用一个唯一的前缀作为它们的前缀,要么就是不要使用它们,并且在你的代码的类OOP布局中自我约束。

模块应该是无状态的。您可以获得灵活性并减少多线程头痛。

+0

只需添加一项:您还可以在“使用”语句中使用唯一的子句,以包含您真正想要的内容,例如类型本身。 – haraldkl

+0

@Stefano:你能否澄清一下“在某些情况下支持子程序导入,以限制损害(尽管它变得不那么通信)”? – bdforbes

+1

@bdforbes:你可以在每个例程中使用你需要的东西,而不是在模块级使用模块。它可能更加多余,并且你失去了交流的机会,因为现在,为了看到你的模块依赖于什么,你需要打开单个例程,而不是仅仅查看模块的初始部分。 –