- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello!
I'm trying to reuse a linked list. The module used to construct the linked list is this: https://jblevins.org/research/generic-list.pdf
module linkedlist implicit none private public :: list_t public :: list_data public :: list_init public :: list_free public :: list_remove public :: list_insert public :: list_put public :: list_get public :: list_next public :: list_change ! A public variable to use as a MOLD for transfer() integer, dimension(:), allocatable :: list_data ! Linked list node data type type :: list_t private integer, dimension(:), pointer :: data => null() type(list_t), pointer :: next => null() end type list_t contains ! Initialize a head node SELF and optionally store the provided DATA. subroutine list_init(self, data) type(list_t), pointer :: self integer, dimension(:), intent(in), optional :: data allocate(self) nullify(self%next) if (present(data)) then allocate(self%data(size(data))) self%data = data else nullify(self%data) end if end subroutine list_init ! Free the entire list and all data, beginning at SELF subroutine list_free(self) type(list_t), pointer :: self type(list_t), pointer :: current type(list_t), pointer :: next current => self do while (associated(current)) next => current%next if (associated(current%data)) then deallocate(current%data) nullify(current%data) end if deallocate(current) nullify(current) current => next end do end subroutine list_free ! Remove element AFTER SELF subroutine list_remove(self) type(list_t), pointer :: self type(list_t), pointer :: current type(list_t), pointer :: next current => self next => current%next current%next = next%next end subroutine list_remove ! Return the next node after SELF function list_next(self) result(next) type(list_t), pointer :: self type(list_t), pointer :: next next => self%next end function list_next ! Insert a list node after SELF containing DATA (optional) subroutine list_insert(self, data) type(list_t), pointer :: self integer, dimension(:), intent(in), optional :: data type(list_t), pointer :: next allocate(next) if (present(data)) then allocate(next%data(size(data))) next%data = data else nullify(next%data) end if next%next => self%next self%next => next end subroutine list_insert ! Change the NEXT node after a element CURRENT to after anOTHER (in other list for example). subroutine list_change(current,other) type(list_t), pointer :: current type(list_t), pointer :: next type(list_t), pointer :: other next => current%next if (associated(next%next)) then current%next => next%next else current%next => null() end if next%next => other%next other%next => next end subroutine list_change ! Store the encoded DATA in list node SELF subroutine list_put(self, data) type(list_t), pointer :: self integer, dimension(:), intent(in) :: data if (associated(self%data)) then deallocate(self%data) nullify(self%data) end if self%data = data end subroutine list_put ! Return the DATA stored in the node SELF function list_get(self) result(data) type(list_t), pointer :: self integer, dimension(:), pointer :: data data => self%data end function list_get ! function list_isnull(self) result(a) ! type(list_t), pointer :: self = .false. ! logical :: a ! if end module linkedlist
The main program is
! A derived type for storing data. module data implicit none private public :: data_t public :: data_ptr ! Data is stored in data_t type :: data_t real :: x end type data_t ! A trick to allow us to store pointers in the list type :: data_ptr type(data_t), pointer :: p end type data_ptr end module data ! A simple generic linked list test program program list_test use linkedlist use data implicit none type(list_t), pointer :: ll => null(), node type(data_t), target :: dat_a type(data_t), target :: dat_b type(data_ptr) :: ptr ! integer, pointer :: p1 ! integer, target :: t1, t2 ! ! p1=>t1 ! p1 = 1 ! ! Print *, p1 ! Print *, t1 ! print*, "A" ! ! deallocate(p1) ! ! print*, "B" ! ! t2 = 2 ! p1 => t2 ! print*, p1 ! ! ! deallocate(p1) ! ! print*, "C" ! Initialize two data objects dat_a%x = 17.5 dat_b%x = 3.0 ! Initialize the list with dat_a ptr%p => dat_a call list_init(ll, DATA=transfer(ptr, list_data)) print *, 'Initializing list with data:', ptr%p ! Insert dat_b into the list ptr%p => dat_b call list_insert(ll, DATA=transfer(ptr, list_data)) print *, 'Inserting node with data:', ptr%p ! Get the head node ptr = transfer(list_get(ll), ptr) print *, 'Head node data:', ptr%p ! Get the next node ptr = transfer(list_get(list_next(ll)), ptr) print *, 'Second node data:', ptr%p print*, associated(node) node => list_next(ll) ! Free the list starting on the secound node (after ll) call list_free(node) node => list_next(ll) print*, associated(node) ! It prints True, but it should be false since I deallocated the next node ! Initialize the list with dat_a ptr%p => dat_a call list_insert(ll, DATA=transfer(ptr, list_data)) print *, 'Initializing list with data:', ptr%p ! Insert dat_b into the list ptr%p => dat_b call list_insert(ll, DATA=transfer(ptr, list_data)) print *, 'Inserting node with data:', ptr%p ! Get the head node ptr = transfer(list_get(ll), ptr) print *, 'Head node data:', ptr%p ! Get the next node ptr = transfer(list_get(list_next(ll)), ptr) print *, 'Second node data:', ptr%p ! try to free it again node => list_next(ll) print*, associated(node), "capivara" call list_free(node) !The code breaks with double free here print*, "lalala" print*, associated(node) end program list_test
When I try to free the list a second time, it crashes and I get double free error. For some reason, even after I deallocate the first time, if I test it, I get that the node still associated. But if I try to require the data that the node stores it crashes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Checked a bit closer: list_data has really never been allocated. No wonder that you cannot transfer it. Next programming error:
print*, associated(node)
Node has never been associated before. So the program stops with a runtime error.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is for sure a programming error:
Runtime Error: main.f90, line 62: ALLOCATABLE LIST_DATA is not currently allocated
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Checked a bit closer: list_data has really never been allocated. No wonder that you cannot transfer it. Next programming error:
print*, associated(node)
Node has never been associated before. So the program stops with a runtime error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>Checked a bit closer: list_data has really never been allocated.
I don't know why it had to be allocated. It is just the mold of the transfer function.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>I don't know why it had to be allocated. It is just the mold of the transfer function
list_data is an (unallocated) array. The mold requires the shape of this array. I suppose for some peculiar reason you might wish to have transfer to construct an unallocated array out of the input arg, but I suspect this was not your intention.
Also, I didn't review your code in depth. But on the surface, it appears that you are attempting to use transfer to convert a data_ptr object into an integer array object. This doesn't make sense. Did you intend to convert ptr%p (the scalar real) into an integer array?
Jim Dempsey

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page