早期的Fortran程序多使用静态数组。在编译时,静态数组被分配固定的存储空间,且在程序运行过程中静态数组的大小是不会改变的。为了能够存储足够多的数据,静态数组的大小需要足够大,这会造成内存的浪费。如果静态数组的大小不够大,程序的运行也可能会出现错误。
在Fortran90标准之后,我们可以很方便地使用可分配数组。使用allocatable属性定义可分配数组,allocate和deallocate语句动态地为数组分配和释放内存。使用size语句可以查询可分配数组的大小(元素总数)。
若一个可分配数组的内存已经被释放了,数组内元素的总数是0。然而,笔者最近发现,仍然用size语句查询其大小,得到的结果却是上一次其被分配的大小。 以下面的测试程序为例:
program size_test implicit none integer,allocatable :: values(:) call modify_size(5) call modify_size(0) contains subroutine modify_size(n) implicit none integer :: n integer :: i if (allocated(values)) deallocate(values) if (n>0) then allocate(values(n)) values = 1 end if write(*,"(A,I0)") "size ofvalues = ",size(values) do i=1,size(values) write(*,"(A,I0,A,I0)")"values(",i,") = ",values(i) end do end subroutine modify_size end program size_test
其中,values作为可分配数组。子程序modify_size通过输入参数n来给values分配内存,若n>0则将values的大小设置为n并赋值values为1,否则不给values分配内存。随后输出values的大小和所有元素的值。主程序中先取modify_size的输入参数为5,再取0。编译程序并运行,输出如下所示:
size of values = 5 values(1) = 1 values(2) = 1 values(3) = 1 values(4) = 1 values(5) = 1 size of values = 5 forrtl: severe (174): SIGSEGV, segmentation faultoccurred Image PC Routine Line Source size_test 000000000040400D Unknown Unknown Unknown libpthread-2.17.s 00002B004C5575E0 Unknown Unknown Unknown size_test 0000000000403150 Unknown Unknown Unknown size_test 0000000000402C1E Unknown Unknown Unknown libc-2.17.so 00002B004C785C05 __libc_start_main Unknown Unknown size_test 0000000000402B29 Unknown Unknown Unknown
第一轮输出完全正确,values的大小被设置成了5,并且数组中的元素全是1。然而第二次调用modify_size时,释放values的内存后没有分配values的大小,size(values)的值还是5。在输出values的值时程序会报错。
这个例子说明当使用可分配数组时,查询可分配数组的大小前需要先查询其是否被分配了内存,即用allocated()查询,否则得到的数组的大小可能是这个数组上一次被分配的大小。
本文分享自微信公众号 - 量子化学(quantumchemistry),作者:zxli
原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。
原始发表时间:2020-12-16
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句