一个简单的可选参数怎么会导致数据损坏?(How could a simple optional ar

2019-07-30 07:36发布

我有一个例程的Fortran代码:

SUBROUTINE READ_NC_VALS(NCID, RECID, VARNAME, VARDATA)
integer ncid, recid
character*(*) varname
real*8 vardata
dimension vardata(15,45,75)

etc.

我想有一定的灵活性添加到这个代码,我想我会首先加入一个可选的标志参数做到这一点:

SUBROUTINE READ_NC_VALS(NCID, RECID, VARNAME, VARDATA, how_to_calculate)

! everything the same and then ...
logical, optional :: how_to_calculate

现在,在这一点上,我甚至没有使用“how_to_calculate”。 我只是把它变成代码进行测试。 所以我编译代码顺利。 然后我运行它,我在子程序得到一个错误。 具体而言,一些代码值的后面是“神奇”,从他们身上所没有的可选参数改变。 新价值是没有意义的代码的逻辑,所以它与一个错误消息礼貌地退出。 让我再次强调,在这一点上,我甚至不使用这个可选参数。 那么,在一个云雀,我回去在调用这个例程和,即使我在选购新的说法,我把价值观它在所有呼叫源的所有地方。 当我这样做,代码运行正常。 那么这是什么一回事? 如何在子程序结果中的其他数据未使用的可选参数的存在本身被破坏? 而如何能为这个可选参数解决的事情再次增加的输入参数? 这是正在编译PGI,顺便说一句。

有任何想法吗? 谢谢。

顺便说一句,对不起,不能提供更多的代码。 我的老板可能不会太高兴我,如果我这样做。 我不制定规则; 我只是在这里工作。

Answer 1:

用Fortran可选参数通过使实现0为不具有由主叫提供的子程序值的每个可选参数(空指针)。 因为这个子程序采取可选参数的有:

  • 要么有一个明确的INTERFACE调用子程序内定义
  • 或者是一个模块级子程序(为它们的接口是自动生成的)

如果添加一个可选的参数传递给一个子程序,但它们都没有在调用者的接口,或者不是一个模块级的子程序,那么编译器不会产生正确的调用序列 - 它会通过更少的参数超出预期。 这可能会在Unix系统中,其中PGI通过了所有的长度提出一个问题CHARACTER*(*)在参数列表的末尾参数(在Windows上它传递长度为下一个参数字符串的地址后)。 一个缺少参数将转移在栈中的长度参数配置(或将它们放在错误的寄存器x64上)导致不正确的长度VARNAME串由接收READ_NC_VALS 。 这可能会导致各种不良行为,包括overwritting内存,不应该根据程序逻辑变“魔术”般地改变的值。



Answer 2:

显然,只需添加一个虚拟参数子程序,使用或不使用optional属性,应该不会造成任何问题。 会发生什么,不过,是改变暴露了一些其他问题的代码,它已经在那里了,但没有造成任何明显的不良影响。

没有任何更多的代码,我们所能做的是猜测,这通常不是真的有用。 弹出进头脑的一件事是明确的接口,使用可选参数时的必要性。 是代码组织成模块?



文章来源: How could a simple optional argument lead to data corruption?
标签: fortran90 pgf