我正在嘗試在 Fortran 中創建一個鏈表結構,用于計算區域中粒子之間的定點迭代。粒子通過計算區域迭代追蹤,每一步的屬性都被存盤;它們與上一次迭代中的粒子屬性互動。
對于這個問題,我有兩個鏈表,一個包含上一次迭代的粒子屬性(list_use,當前通過域跟蹤的粒子與之互動)和另一個串列,它在粒子通過計算跟蹤時累積粒子的屬性區。在一次迭代之后(即在所有粒子通過域跟蹤一次之后),我想丟棄list_use(已經計算了與此資料的互動),復制list_buildup到list_use然后丟棄list_buildup,以便可以用下一個資料重新填充它迭代。
復制和丟棄串列時,我似乎有記憶體泄漏。這是復制記憶體泄漏的簡化代碼。據我所知,泄漏發生在updateASR. 我希望這個子例程之前的行程記憶體等于它之后的記憶體,但是使用 VisualStudio 上的診斷,它顯示每次updateASR呼叫時記憶體都會增加,最終導致程式終止(出現訪問沖突錯誤)。這是顯示 VS 行程記憶體診斷的影像。我想這destroyASREntries在某種程度上沒有做我真正想要做的事情?
我對 Fortran 中的指標不是很有經驗,因此有點卡住,所以任何幫助都將不勝感激!
module linked_list
!---------------------------------------------------------------------------------
! Type containing the data for an ASR entry, used to compute interactions between rays.
type ASR_entry
real :: intensity !<- The intensity of the ASR entry
real :: ang_freq !<- Angular frequency
real,dimension(3) :: wavevector !<- Wavevector (x,y,z): Cartesian.
end type ASR_entry
!---------------------------------------------------------------------------------
! A node type in the linked list for the ASR.
type ASR_Node
type(ASR_Node),pointer :: next => null()
type(ASR_Node),pointer :: prev => null()
type(ASR_entry) :: node_entry
end type ASR_Node
!---------------------------------------------------------------------------------
! For interaction, each cell contains one of these ASR linked lists, which itself contains the nodes, which contain the entry.
type ASR_cell_ll
type(ASR_Node),pointer :: head => null() !<- first%next points to first node
type(ASR_Node),pointer :: last => null() !<- last%prev points to last node
integer(kind=4) :: size = 0 !<- Number of ASR entries in the linked list
end type ASR_cell_ll
contains
!---------------------------------------------------------------------------------
! Create the ASR linked list in every cell.
subroutine createASRcell(list)
implicit none
type(ASR_cell_ll), pointer :: list
if(associated(list)) call Abort("Must pass null pointer of type 'ASR_cell_ll' to createASRcell.")
!- Allocate memory - is this necessary??
allocate(list)
allocate(list%head,list%last)
list%head%next => list%last !<- If list is empty, then the first entry points to the last entry which is null
list%last%prev => list%head
list%size = 0
end subroutine createASRcell
!---------------------------------------------------------------------------------
! Delete all ASR entries
subroutine destroyASREntries(list)
implicit none
type(ASR_cell_ll), pointer :: list
type(ASR_Node), pointer :: dCurrent=>null(), dNext=>null()
if (.not. associated(list)) return
allocate(dCurrent,dNext)
dCurrent => list%head
dNext => dCurrent%next
!- Deallocate all data nodes in list
do
nullify(dCurrent%prev) !- Remove dangling pointers from the list structure.
deallocate(dCurrent)
if (.not. associated(dNext)) exit
dCurrent => dNext
dNext => dCurrent%next
end do
nullify(dCurrent,dNext) !- Remove dangling pointers
list%size=0
deallocate(list)
end subroutine destroyASREntries
!---------------------------------------------------------------------------------
!- This subroutine removes the old entries in list_use, copies the list_buildup entries into list_use, then empties list_buildip for the next iteration.
subroutine updateASR(list_use, list_buildup)
implicit none
type(ASR_cell_ll),pointer :: list_use, list_buildup
!First destroy all entries from the previous ASR iteration, before recreating the list.
call destroyASREntries(list_use)
call createASRcell(list_use)
!Then make the use list the previous iterations buildup list.
list_use => list_buildup
!The stop buildup from pointing to the use list's new entries, before recreating buildup as blank.
nullify(list_buildup)
call createASRcell(list_buildup)
end subroutine updateASR
end module linked_list
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module definitions
implicit none
integer :: nx,ny,nz,nbeams !Dimensions of the linked list domain.
integer :: ix,iy,iz,ibeam !Loop variables
end module definitions
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program main
use definitions
use linked_list
implicit none
type(asr_cell_ll),pointer :: list_use,list_buildup !<-The temporary and used linked list.
integer :: i
call createASRcell(list_buildup)
call createASRcell(list_use)
do i=1,1000000000
call updateASR(list_use,list_buildup)
enddo
end program main
我用 ifort 編譯了上面的內容。
uj5u.com熱心網友回復:
首先,讓我們看一下createASRcell。它回傳一個ASR_cell_llwith size=0。那么為什么要分配記憶體呢?只有在需要節點時才應分配節點。我認為createASRcell應該是
subroutine createASRcell(list)
type(ASR_cell_ll), pointer :: list
if(associated(list)) call Abort("Must pass null pointer of type 'ASR_cell_ll' to createASRcell.")
list%head => null()
list%last => null()
list%size = 0
end subroutine
其次,我們來看看destroyASREntries。線條
allocate(dCurrent,dNext)
dCurrent => list%head
dNext => dCurrent%next
正在創建兩個節點 atdCurrent和dNext,然后立即失去對這些節點的跟蹤以指向dCurrent新dNext目標。這將泄漏您剛剛分配的記憶體。該allocate宣告不應該存在。還有相當多的過度釋放。簡化子程式,我們得到
subroutine destroyASREntries(list)
type(ASR_cell_ll), pointer :: list
type(ASR_Node), pointer :: dCurrent, dNext
if (.not. associated(list)) return
dCurrent => list%head
!- Deallocate all data nodes in list
do while(associated(dCurrent))
dNext => dCurrent%next
nullify(dCurrent%prev)
nullify(dCurrent%next)
deallocate(dCurrent)
dCurrent => dNext
end do
! - Deallocate the list itself
deallocate(list)
end subroutine destroyASREntries
最后,我們來看看updateASR。我不太明白您要在這里做什么,但是子例程會引起問題。線條
call destroyASREntries(list_use)
call createASRcell(list_use)
list_use => list_buildup
將清理舊的ASR_cell_ll指向 by list_use,創建一個新的空串列ASR_cell_ll,再次指向 by list_use,然后通過指向立即失去對這個新串列的list_use跟蹤list_buildup。這將泄漏新創建的所有記憶體ASR_cell_ll。
uj5u.com熱心網友回復:
感謝@veryreverie 的回答,幫助解決了泄漏并消除了我的誤解。createASRcell問題是由于在將指標重新指向和中的新記憶體之前分配了指標destroyASREntries。這是顯示沒有記憶體泄漏的新代碼的診斷。如果有人感興趣,這是修改后的作業代碼,沒有記憶體泄漏:
module linked_list
!---------------------------------------------------------------------------------
! Type containing the data for an ASR entry, used to compute interactions between rays.
type ASR_entry
real :: intensity !<- The intensity of the ASR entry
real :: ang_freq !<- Angular frequency
real,dimension(3) :: wavevector !<- Wavevector (x,y,z): Cartesian.
end type ASR_entry
!---------------------------------------------------------------------------------
! A node type in the linked list for the ASR.
type ASR_Node
type(ASR_Node),pointer :: next => null()
type(ASR_Node),pointer :: prev => null()
type(ASR_entry) :: node_entry
end type ASR_Node
!---------------------------------------------------------------------------------
! For interaction, each cell contains one of these ASR linked lists, which itself contains the nodes, which contain the entry.
type ASR_cell_ll
type(ASR_Node),pointer :: head => null() !<- first%next points to first node
type(ASR_Node),pointer :: last => null() !<- last%prev points to last node
integer(kind=4) :: size = 0 !<- Number of ASR entries in the linked list
end type ASR_cell_ll
contains
!---------------------------------------------------------------------------------
! Create the ASR linked list in every cell.
subroutine createASRcell(list)
implicit none
type(ASR_cell_ll), pointer :: list
if(associated(list)) call Abort("Must pass null pointer of type 'ASR_cell_ll' to createASRcell.")
allocate(list)
allocate(list%head,list%last)
list%head%next => list%last !<- If list is empty, then the first entry points to the last entry which is null
list%last%prev => list%head
list%size = 0
end subroutine createASRcell
!---------------------------------------------------------------------------------
! Delete all ASR entries
subroutine destroyASREntries(list)
implicit none
type(ASR_cell_ll), pointer :: list
type(ASR_Node), pointer :: dCurrent=>null(), dNext=>null()
if (.not. associated(list)) return
dCurrent => list%head
!- Deallocate all data nodes in list
do while(associated(dCurrent))
dNext => dCurrent%next
nullify(dCurrent%prev) !- Remove dangling pointers from the list structure.
nullify(dCurrent%next) !- Remove dangling pointers from the list structure.
deallocate(dCurrent)
dCurrent => dNext
end do
! - Deallocate the list itself
deallocate(list)
end subroutine destroyASREntries
!---------------------------------------------------------------------------------
!- This subroutine removes the old entries in list_use, copies the list_buildup entries into list_use, then empties list_buildip for the next iteration.
subroutine updateASR(list_use, list_buildup)
implicit none
type(ASR_cell_ll),pointer :: list_use, list_buildup
call destroyASREntries(list_use) !First destroy all entries from the previous ASR iteration
list_use => list_buildup !Then make the use list the previous iterations buildup list.
nullify(list_buildup) !The stop buildup from pointing to the use list's new entries
end subroutine updateASR
end module linked_list
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module definitions
implicit none
integer :: nx,ny,nz,nbeams !Dimensions of the linked list domain.
integer :: ix,iy,iz,ibeam !Loop variables
end module definitions
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program main
use definitions
use linked_list
implicit none
type(asr_cell_ll),pointer :: list_use=>null(),list_buildup=>null() !<-The temporary and used linked list.
integer :: i
call createASRcell(list_buildup)
call createASRcell(list_use)
do i=1,1000000000
call updateASR(list_use,list_buildup)
enddo
end program main
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/462797.html
