在C和C ++中,有许多操作会导致未定义的行为,即允许编译器执行所需操作的情况。 Examples包括在分配变量后使用变量,分配两次变量并取消引用空指针。
Fortran是否也具有未定义的行为?我看了一份规范草案,但未能在其中找到任何东西。例如,在释放变量后使用变量肯定会导致程序崩溃,还是它会默默地做错事?
答案 0 :(得分:10)
是的。只是被称为不同。您可以做很多事情,并且会使您的代码不符合标准的要求,因此不需要处理器(编译器)诊断此类不符合项(当然,必须进行许多偏离)被诊断)。通常情况将类似于C的未定义行为(例如,超出范围访问数组,有符号整数溢出等)。我们只是说该代码不符合标准,这意味着该标准并未规定此类代码的结果。此类代码未涵盖在标准中,因此,如果某些编译器(处理器)对它进行编译并且您运行了它,则可能会产生任何内容。
与依赖处理器的行为不同,它是标准的,仅依赖于实现。
只需在StackOverflow上进行搜索即可为您提供大量示例。像Is passing the same entity to arguments with different intent undefined behavior? How do Fortran and MPI_Reduce deal with integer overflow?
答案 1 :(得分:10)
Fortran标准确实接受与C和C ++的“未定义行为”概念类似的概念。支持断断续续的Fortran代码的人经常将其表述为“编译器现在可能开始第三次世界大战”或类似的内容。
Fortran语言规范具有两个一致性概念(请参阅Fortran 2018,4.2)。最主要的是程序必须具有什么样的外观才能被视为Fortran程序。第二个是处理器必须响应提交的程序单元才能被视为Fortran处理器。
如果要求兼容的Fortran处理器处理非Fortran程序的内容,则标准很少说明必须发生的情况。必须提供一些诊断,但通常没有。
在“在释放变量之后使用变量”的情况下,尝试这样做是违反了定义Fortran 程序的语言标准的那部分。然后,编译器可能会在不违反Fortran标准的情况下“发动第三次世界大战”,因为Fortran标准并未说它不能(或必须做其他事情)。
现在,我们如何看待Fortran标准文档并确定非完全Fortran程序是否具有特定的必需作用? 4.2中的文本提到了编译器必须具有“在提交的程序单元中检测和报告使用情况的能力”的许多情况。如果您提出的程序没有成功,那么您属于“未定义”领域。
通常情况下必须报告程序错误
在已提交的程序单元中使用编号的语法规则或约束所不允许的形式或关系
让我们任意考虑Fortran 2018,15.5.1C1523(R1520)过程参考的语法。我们看到类似“ R1520”的东西:
R1520 功能参考是过程指示符([ actual-arg-spec-list ])
和“ C1523”:
C1523(R1520)过程代号应指定一个功能。
之前,我们有类似的清单:
过程指示符中的数据引用不得是未分配的可分配变量或不相关的指针。
在这种情况下,规则R1520,编号为约束C1523(适用于此规则)和以下文本给出了对Fortran程序的约束。如果您提交的程序不符合要求,则说明它不是符合标准的Fortran程序。
被要求处理这种不合格程序的编译器必须能够检测到该不合格程序(基于上述内容),该程序不符合R1520或C1523。编译器不必抱怨或检测到未编号文本的冲突。可以假定所提供的任何程序都不会违反这种未编号的限制。
我在这里引用的这个(巧合地)是禁止程序错误地使用先前释放的变量的一个示例。
如果处理器以“先编译后运行”的方式运行,则编号的规则/约束通常是可以在“编译时”进行评估的规则/约束。