fortran - 英特尔 FORTRAN 中的解除分配

标签 fortran

我在使用一些现有的 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 两次,而没有先解除分配。根据这本书,这应该会导致程序终止。它不仅可以工作,而且可以正确工作,并且第二次 ALLOCATE 返回的 STAT 为“0”。

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

最佳答案

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

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

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

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

关于fortran - 英特尔 FORTRAN 中的解除分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15554289/

相关文章:

Fortran:0.d0 总是 == 0 吗?

arrays - 输出3D数组的算法

arrays - 派生类型数组 : select entry

arrays - FORTRAN 数组计算错误

fortran - Fortran+openMP 的简单分析?

node.js - Fortran 中的生成进程

fortran - 数组构造函数中的不同字符长度(3/4),如何修剪字符串 - fortran

matlab - Fortran 和 Matlab 返回同一矩阵的不同特征值

c - 用于数组和标量的 Fortran 到 C 接口(interface)

c++ - Rcpp 无法动态加载库 : Missing __si_class_type_info