【问题标题】:If i call a function in fortran, without defining a variable, what happens?如果我在 fortran 中调用函数而不定义变量,会发生什么?
【发布时间】:2013-10-07 18:50:13
【问题描述】:

所以我有一个程序,里面有这样的东西:

integer :: mgvn, stot, gutot, iprint, iwrit, ifail, iprnt
...
call readbh(lubnd,nbset,nchan,mgvn,stot,gutot,nstat,nbound,rr,bform,iprnt,iwrit,ifail)

然后在readbh里面:

      CALL GETSET(LUBND,NSET,KEYBC,BFORM,IFAIL)
      IF(IFAIL.NE.0) GO TO 99
      ...
 99   WRITE(IWRITE,98) NBSET,LUBND
      IFAIL = 1
      RETURN

所有其他变量都已定义,但 ifail 未定义。如果我在函数调用之前添加write(*,*) ifail,我会得到未定义的变量错误,但如果我把它排除在外,它不会抱怨,只是与函数一起跑掉,总是失败,IFAIL=1

这是因为它刚刚到达 readbh 函数中参数的末尾,读取未初始化的内存 - 这只是随机的乱码 - 然后将这些位转换为 int - 这不会零,除非我很(不)幸运,所以几乎总是让ifail.ne.0true

【问题讨论】:

  • 您是没有定义 ifail 还是将其从调用 arg 列表中删除?访问未定义的变量就是未定义的。它可能为零,或者可能是该内存位置中发生的任何垃圾。如果您在子例程中访问甚至没有提供的 args,您可能会遇到段错误。
  • -Wuninitialized 标志是有原因的...

标签: fortran fortran90


【解决方案1】:

我会选择将您所谓的未定义变量解释为未初始化变量。一般来说,Fortran 和许多其他编译型编程语言会很乐意使用未初始化的变量进行计算。它/它们是成年人的编程语言,如果你对这种行为进行编程,那是我们自己的事。编写使用未初始化变量的 Fortran 程序在语法上并非不正确,因此编译器不受语言标准的约束以引发警告或错误。

不过,Fortran 确实可以让您对函数和子例程进行编程,以确保给定输出参数。如果你在过程中对应该有赋值的参数使用intent(out) 属性,那么编译器将检查是否进行了赋值,如果没有赋值则会引发错误。

大多数编译器都有一个选项来执行运行时检查以检查未初始化变量的使用。例如,英特尔 Fortran 具有标志 -check:uninit。如果没有这个检查,是的,您的程序会将它在标记为ifail 的内存区域中找到的任何位模式解释为整数并继续。

您写道,您的函数总是以ifail == 1 失败。从您向我们展示的ifail 来看,就在return 之前(可能)在对readbh 的调用结束时,无条件设置为1

从您透露的代码来看,在我看来,ifail 似乎是来自getset 的错误返回代码,因此在进入该子例程时未初始化它不一定是错误的。但有点令人费解的是readbh然后在返回之前将其设置为1

【讨论】:

  • IFAIL 是一个变量,它作为最后一个变量传递给整个代码中的许多例程,并且在所有地方它只是检查它的值是什么,其中一些只是结束程序.在示例中,getset 中有一个子句检查 IFAIL 是否为 0,如果不是,则将其设置为 1 并且不返回任何内容。
  • ifort 还有一个标志,它会自动将所有未初始化的(数字)变量初始化为 0(我认为是 -zero)。我并不是建议让编译器初始化变量是一种好习惯,但如果你继承了糟糕的代码,它是可用的。
猜你喜欢
  • 2023-04-05
  • 1970-01-01
  • 2011-04-02
  • 1970-01-01
  • 2016-08-14
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
相关资源
最近更新 更多