【发布时间】:2011-09-23 01:08:33
【问题描述】:
我需要一个 Fortran 中的可变大小数组。在 C++ 中,我会使用向量。所以我有一个类似
的功能integer function append(n, array, value)
integer, pointer, dimension(:) :: array
integer, pointer, dimension(:) :: tmp_arr
integer n
if (size(array) .eq. n) then
allocate(tmp_arr(2*size(array)))
tmp_arr(1:size(array)) = array
deallocate(array)
array => tmp_arr
end if
n = n + 1
array(n) = value
append = n
end function
如果我这样使用它会很好用
integer pos, val
pos = append(n, array, val)
但是,如果我想以这种方式使用它
integer i,j,n ! i,j<n
array(i) = append(n, array, array(j))
使用 gfortran 这不起作用。它编译,但段错误。问题似乎是gfortran从array(i)和array(j)中生成地址,将后者发送到函数append,然后当array(j)的地址被访问并且array(i)的地址被写入时,地址空间已被释放。
我想要的是数组(j)的值被放入堆栈(而不是地址),然后在函数中使用,在函数完成后查找数组(i)的最新地址并函数的结果保存到它。
我很确定 gcc 会按照我想要的方式做,为什么 gfortran 如此卑鄙?
在 Fortran 中有什么方法可以使一个健壮的(意味着 array(j) = ... 示例有效) 具有类似 c++ stl 向量的行为的函数或数据类型?
结论:
我最终引入了临时变量
integer tmp_val
tmp_val = value
...
array(n) = tmp_val
所以至少该方法可以称为
pos = append(n, array, array(j))
array(i) = pos
并希望该项目的其他/未来开发人员不会尝试“优化”这两条线以消除“pos”的必要性。
感谢您的回答和cmets。
【问题讨论】:
-
如果你用 -C 编译(检查边界标志)并重新运行,你会得到什么消息?
-
我没有收到任何消息,并且分段违规仍然存在。
-
呃,有副作用和指针的函数;你一定会遇到麻烦。不要尝试在 Fortran 中编写 C++。 (虽然我们都知道真正的程序员可以用任何语言编写 Fortran。)
-
除了建议的答案之外,您可以在输入函数之前将
array(j)复制到不同的变量中。您应该始终警惕 fortran 中的这些事情,例如像append(10, array, val)这样调用你的函数也会出现段错误,所以你最好使用integer, intent(inout) :: n。 -
@steabert:感谢您的提示,我发布它的方式是正确的。在代码 n 的真实版本中,在模块上使用了数组,函数的调用方式类似于 array(i) = append(array(j))
标签: fortran