我有以下问题:如何取消分配类型的数组内存?像%b%c一样 我该如何分配c?具体的问题是(我尝试过的编译器环境是gfortran版本gcc4.4.7和ifort版本18.0.1.OS:linux):
repeat.for
首先,使用“ gfortran main.F90 -o main”来编译程序,然后运行该程序。然后,我使用top -p processID来查看内存。当程序执行到1时,内存为4.5G。当程序执行到2时,内存为7.5G。当程序执行到3时,内存也为7.5G(但我认为是4.5G)。当程序执行到4时,内存为3G(我认为是0G或接近0G)。因此,deallocate(a%b(i)%c)似乎不起作用。但是,我使用valgrind查看内存。该程序的内存全部是可释放的...我使用了ifort和gfortran。无论我使用哪个编译器,都会发生此问题。如何解释这个问题?我以这种方式分配了很多c数组,由于内存不足,程序最终将崩溃。以及如何解决?
答案 0 :(得分:2)
在英特尔论坛上查看this post。其中有2条重要信息:
(来自Forran医生):
执行DEALLOCATE时,分配的内存将返回到内存分配器使用的池(在Linux和OS X上,这与C的malloc / free相同)。内存不会释放回操作系统-很少有这种可能性。经常发生的情况是,分配和释放模式会导致虚拟内存碎片化,因此尽管总可用空间可能很大,但可能没有足够的连续空间来分配大项目。与磁盘不同,无法对内存进行“碎片整理”。
(来自Jim Dempsey)
查看是否可以按照相反的顺序取消分配内存。这样可以减少内存碎片。
您也可以参考this other英特尔文章:
在程序运行期间,Fortran运行时库将管理您的堆。是的,如果已取消分配数据,则运行时可以选择等待释放该内存。这是一种优化-如果您执行另一个相同大小的ALLOCATE,它将仅重复使用这些页面。如果堆开始耗尽,它将进行一些收集,但是直到绝对必要时才进行收集。
此外,让我添加一些内容:检查是否在范围内没有动态创建其他对象,例如自动数组或临时数组副本。那可能是要求很高的内存,只有它们超出范围时才可以释放它们。
总结一下,即使'top'表示内存仍在使用中,您也应该开始担心,除非您的程序开始崩溃或Valgrind显示出一些麻烦。
答案 1 :(得分:0)
我修改了程序(以查看程序的运行位置),并在Windows 7 / gFortran 7.2.0上运行。报告中没有显示内存保留,因为内存恢复为13 mb。与我的评论相反,在初始化c期间内存需求没有变化。
module grist_domain_types
implicit none
public :: aaa
type bbb
real (8), allocatable :: c(:)
end type bbb
type aaa
type(bbb), allocatable :: b(:)
end type aaa
end module grist_domain_types
program main
use grist_domain_types
type(aaa) :: a
integer(4),parameter :: million = 1000000
integer(4) :: n = 100*million
integer(4) :: time = 5, i, pass
do pass = 1,5
write (*,*) ' go #', pass
allocate(a%b(1:n))
write (*,*) 'allocate b'
call sleep(time)!--------------1
write (*,*) ' go'
do i=1,n
allocate(a%b(i)%c(1:1))
enddo
write (*,*) 'allocate c'
call sleep(time)!--------------2
write (*,*) ' go'
do i=1,n
a%b(i)%c = real(i)
enddo
write (*,*) 'use c'
call sleep(time)!--------------2a
write (*,*) ' go'
do i=1,n
deallocate(a%b(i)%c)
enddo
write (*,*) 'deallocate c'
call sleep(time)!--------------3
write (*,*) ' go'
deallocate(a%b)
write (*,*) 'deallocate b'
call sleep(time)!--------------4
end do
write (*,*) ' done : exit ?'
read (*,*) i
end program
edit:我给测试做了一次重复,通过...来重复内存需求。这表明此Fortran程序没有内存泄漏。我使用任务管理器来标识此程序和O / S的内存使用情况。您特定的操作系统和Fortran编译器可能有所不同。