0

我已经很好地浏览了以前的帖子,我认为这个话题已经被覆盖了,希望有人能提供帮助。我正在用 fortran 2003 编写代码,并使用 ifort。我有以下需要操作的类型,我设计了这些类型以提供所需的灵活性:

module parameters    

double precision, target :: cur_x(3)    

    type fundamental
            double precision, pointer   ::  x => null()
    end type fundamental

    type, extends(fundamental) :: ion
            class(fundamental), pointer ::  core => null()
     end type ion

SAVE
end module parameters

这个想法是我通过使用列表中的前一个作为下一个的核心来构建一种粒子链表。请注意,实际上我会对“基本”进行大量扩展,所有这些都可以成为其他粒子的“核心”。我希望计算的数量 x 一起在物理内存中的一个数组中,因为我将以相当复杂的方式寻址它们的子集,为此我想使用另一组指向 cur_x 的指针

代码的初始化是这样的,我在其中添加了一些诊断行:

use parameters

    type(fundamental), target :: electron, proton
            type(ion), target :: hydrogen

    write(*,*)associated(electron%x),associated(proton%x), &
                   & associated(hydrogen%core),associated(hydrogen%core%x)

        electron%x => cur_x(1)

        hydrogen%core => proton
        proton%x => cur_x(2)
        hydrogen%x => cur_x(3)

        cur_x = 1.0

    write(*,*)electron%x,proton%x,hydrogen%x,hydrogen%core%x

哪个打印

F F F T
1.0 1.0 1.0 <garbage>

我希望质子%x 和氢%core%x 是内存中的相同地址(cur_x(2))。所以我有两个问题

  1. 我已将所有指针初始化为空。为什么 associated(hydrogen%core%x) 给出真实的?如果我尝试在代码顶部取消这个指针,我会得到不一致的结果;使用

    nullify(hydrogen%core%x)
    

    导致分段错误。表演

    hydrogen%core%x => null()
    

    允许代码运行,但 associated(hydrogen%core%x) 保持为真

  2. 我已确保将指针列表从父级关联到子级,正如本 fortran 中令人惊讶的错误摘要中所建议的那样。proton%x 工作但hydro%core%x 产生垃圾的事实是我不明白的。

我可以解决这个问题,但这会牺牲我进行更复杂计算所需的一般性。我也很想了解这里出了什么问题。

谢谢你的帮助!吉姆

编辑:为各种事物添加了“目标”属性;请注意,这总是在代码中,我只是在转移到这篇文章时忘记了它们

编辑:澄清一下,我对上述代码的主要问题是最终的写入命令为hydro%core%x 提供了未初始化的输出,即使在第一次写入后遵循关联命令也是如此。尽管我在类型定义中将 core 初始化为 null,但它似乎存在问题;如果我尝试在代码顶部取消它,程序就会崩溃。

4

2 回答 2

2

基本问题是hydrogen%core没有关联。因此, 的影响associated(hydrogen%core%x)是不确定的。您不能访问/查询x派生类型指针 ( ) 的字段 ( hydrogen%core),如果指针未关联,例如指向null()而不是内存中现有的派生类型实例。您的编译器可能会生成一个代码,当您尝试它时不会立即崩溃,但之后所做的任何事情都是不确定的,因为您可能已经覆盖了随机内存地址的一些数据。

实际上,我使用各种编译器编译了您的代码的自包含版本(见下文),并且在第一个 write 语句时立即出现了段错误。使用适当的检查选项,其中一个二进制文件甚至会报告原因是在引用未关联的指针hydrogen%core。如果您注释掉有问题的associated()查询(如下面的代码),所有二进制文件都可以正常运行。

另外,请注意,变量electronproton必须具有目标属性,否则代码根本不应该编译。如果您的编译器编译代码时没有抱怨,您可能应该考虑更改为另一个。

  module parameters    
  implicit none
  save

  type :: fundamental
    double precision, pointer ::  x => null()
  end type fundamental

  type, extends(fundamental) :: ion
    class(fundamental), pointer ::  core => null()
  end type ion

end module parameters

program test
  use parameters
  implicit none

  type(fundamental), target :: electron, proton
  type(ion) :: hydrogen
  double precision, target :: cur_x(3)

  ! If you remove the comment in the next statement, the program will be indeterministic
  ! and probably crash.
  write(*,*) associated(electron%x),associated(proton%x), &
      & associated(hydrogen%core)!, associated(hydrogen%core%x)

  electron%x => cur_x(1)
  hydrogen%core => proton
  proton%x => cur_x(2)
  hydrogen%x => cur_x(3)
  cur_x(:) = 1.0
  write(*,*)electron%x,proton%x,hydrogen%x,hydrogen%core%x

end program test
于 2013-03-12T22:51:44.017 回答
2
  1. 如果hydrogen%core没有关联,那么hydrogen%core%x在第一个 write 语句中引用(或定义)是一个编程错误。出现该编程错误后,任何事情都会从那时开始。

  2. 您没有说您使用的是哪个版本的 ifort,但存在与多态指针有关的编译器错误(如果我记得英特尔论坛上最近的帖子,我认为这些错误已经存在)。

除此之外,为了hydrogen%core指向局部proton变量,质子必须具有 TARGET 属性。我希望编译器能够诊断这一点。

于 2013-03-12T22:52:48.203 回答