2

我在使用一些现有的 FORTRAN 代码时发现了一个问题。尽管它已经预料到需要在重新分配之前释放数组,但这从来没有必要。我现在需要它来执行此操作,但它无法正常工作。

目前的伪代码大概是:

MODULE mA
  TYPE A
    REAL, DIMENSION(:,:,:), ALLOCATABLE :: array
  END TYPE
  TYPE (A), POINTER :: sw(:)
END MODULE

后来,有分配“数组”大小的代码,我现在调用了两次(迄今为止只有一次):

...
IF (ALLOCATED(sw(1)%array))  DEALLOCATE(sw(1)%array, STAT=aviFail)

IF (aviFail.EQ.0) ALLOCATE(sw(1)%array(1,2,3), STAT=aviFail)
...

我查看了 ALLOCATE、DEALLOCATE 和 ALLOCATED 的定义,发现如下:

  1. 在第二次通过时,调用 DEALLOCATE,但 STAT 值为 '1'
  2. 在失败的情况下(即一个积极的 STAT 返回),DEALLOCATE 意味着保持原始数组不变。它没有:它显然正确地清除了它(至少,根据调试器)。
  3. 在失败且未定义 STAT 的情况下,DEALLOCATE 意味着终止程序。它没有,但以下 ALLOCATE 语句失败,STAT 值为“1”。

我还无意中在其他地方两次调用了同一个数组上的 ALLOCATE,而没有先 DEALLOCATING。根据这本书,这应该会导致程序终止。它不仅可以工作,而且可以正常工作,并且第二个 ALLOCATE 的 STAT 返回为“0”。

英特尔 FORTRAN 是否以不同的方式处理这些事情,或者 FORTRAN 在满足其规范方面不像 C++ 那样挑剔?

4

1 回答 1

3

没有看到更多的实现,很难给出详细和有针对性的解释,但我认为这很可能是导致您的问题的指针的实现。您给出的关于 ALLOCATE 和 DEALLOCATE 行为的“书”答案听起来是正确的,但您描述了它们在直接使用可分配数组时的行为方式。对指针进行操作时,ALLOCATE 和 DEALLOCATE 的功能可能不同(取决于编译器)。在最基本的层面上,通过指针分配内存需要更多步骤:1)确定要为指针创建的对象的类型/维度,2)在内存中创建并分配该类型/维度的未命名对象,3)关联带有新对象的指针。根据实现,编译器,

在这个实现中使用指针有什么特别的原因吗?如果没有,我建议切换到更简单的普通可分配数组,看看问题是否仍然存在。

关于您能够在没有预期程序终止的情况下错误地分配和排列两次:我认为这也与您使用指针的实现有关。您正在重新分配的指针已经与内存中的某个位置相关联。这种关联很可能会改变编译器在第二次执行时处理 ALLOCATE 语句的方式。如果指针已经与具有 ALLOCATE 语句要求的维度的内存位置相关联,则没有理由终止程序或引发错误;程序员得到的正是他或她所要求的。

最后,ALLOCATE/DEALLOCATE 语句和指针关联/无效由不同的编译器以不同的方式处理,因此您的观察行为与“书”不符也就不足为奇了。我建议您看看您是否真的需要指针实现,并确保在编写代码时应用内存管理最佳实践。

于 2013-05-09T22:12:15.073 回答