【问题标题】:Fortran internal write suddenly an error according to Intel compilerFortran内部写入突然根据Intel编译器报错
【发布时间】:2021-12-14 00:35:21
【问题描述】:

我正在处理的 Fortran 代码有几行类似于

WRITE(filename, '(A16,"_",I4,".dat")') filename, indx

此代码已在许多不同平台和几乎所有主要编译器上成功编译和运行数百次。但是突然间,最新的(或者,无论如何,新的)英特尔编译器不喜欢它了。它会发出警告消息"forrtl: .... Internal file write-to-self; undefined results"。此行执行后,合理的字符数组"filename"变为空白。

我想问题在于filename 既是写入的输入,也是内部写入的目的地。修复很容易。它可以将filename 替换为filename_tmp 之类的目标。但正如我所说,直到现在这才没有必要。

所以我想知道,文件名作为输入和目标是否违反了 Fortran 标准,但是所有这些编译器多年来一直对此视而不见,现在英特尔变得越来越严格了?还是英特尔“势利”?还是彻头彻尾的越野车?

【问题讨论】:

  • 虽然这个输出语句是不允许的,但你可以使用赋值来做类似的事情:filename=TRIM(filename)//'_'//int2str(indx)//'.dat(虽然丑)而不是使用临时副本。关键区别在于赋值语句在赋值之前会完全评估右侧。
  • 最好添加接受/不接受的编译器版本,让其他想知道他们是否有同样问题的人更清楚。
  • 这看起来根本不对。即使编译器可以接受,Fortran 也会在您运行时发出运行时错误(记录结束),因为您尝试写入 filename 本身加上另外 9 个字符。此外,即使您将第二个filename 替换为trim(filename),并且假设修剪后的filename 仍然有9 个字符,gfortran 也会发出运行时错误。 francescalus 建议的字符串连接只是最优雅的解决方案。
  • @Pap,该 write 语句不写 filename 加 9 个字符:它写 前 16 个字母(或更少)filename 加上更多。如果character(len=25) filename 则没有问题。
  • @francescalus 正确。但即使len(filename)>=25 这看起来不正确。当我阅读那个 write 语句时,我立刻想到“为什么不连接字符串呢?”。

标签: io fortran intel-fortran


【解决方案1】:

问题的write语句的

执行1一直是明确禁止的。

我们目前看到(F2018 12.6.4.5.1 p7):

在执行指定内部文件的输出语句期间,该内部文件的任何部分均不得作为评估任何输出列表项的结果而被引用、定义或变为未定义。

filename 是一个内部文件,输出列表项filename 的评估是对该内部文件的引用。

这不是编译器需要检测的编程违规,因此您可以将其视为根据需要改进编译器的诊断能力/挑剔性的情况。编译器的这种行为变化不会损害任何 Fortran 程序。

当然,Fortran 66 没有内部文件(或字符类型),而且 Fortran 77、90 和 95 使用不同的词来实现相同的效果(例如,参见 F90 9.4.4):

如果指定了内部文件,则输入/输出列表项不得在文件中或与文件关联。

如果这看起来更具限制性,从 Fortran 2003 开始​​,输入和输出语句的限制将单独说明(上面仅引用了输出,输入为 p8)。


1 注意执行的使用:语句本身作为语句没有错。它允许存在于未达到的源代码中。编译的时候检查这个语句不是一件简单的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 2014-12-28
    • 2012-05-03
    相关资源
    最近更新 更多