【问题标题】:Insertion sort with a linked list, "Segmentation fault - invalid memory reference" - Fortran带有链表的插入排序,“分段错误 - 无效的内存引用” - Fortran
【发布时间】:2020-08-29 23:03:34
【问题描述】:

我正在尝试使用链表进行选择排序。但是,我收到了分段错误。

"""

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:  
\#0  0x7f191e86a32a   
\#1  0x7f191e869503   
\#2  0x7f191e49cf1f  
\#3  0x7f191e9e9330  
\#4  0x7f191e9ed0b4  
\#5  0x7f191e9e423c  
\#6  0x7f191e9e46dc  
\#7  0x55ed5c77be79  
\#8  0x55ed5c77bfa6  
\#9  0x7f191e47fb96  
\#10  0x55ed5c77b9c9  
\#11  0xffffffffffffffff  
Segmentation fault (core dumped)

"""

我确信这是我尝试在“输出”do 循环之间写出数据时造成的。我发现很难看出我是如何搞砸记忆的。

非常感谢任何帮助!非常感谢您!

program insertion_sort
implicit none

! Derived data type to store integer values in 
type int_value
  integer                   :: value
  type (int_value), pointer :: next_value
end type

! Data dictionary: declare variable types & definitions
type (int_value), pointer :: head       ! Pointer to head of list
character(20)             :: filename   ! input data file name
integer                   :: istat      ! status: 0 for succes
integer                   :: nvals = 0  ! Number of data read
type (int_value), pointer :: ptr        ! Ptr to new value
type (int_value), pointer :: ptr1       ! Temp ptr for search
type (int_value), pointer :: ptr2       ! Temp ptr for search
type (int_value), pointer :: tail       ! Pointer to tail of list
integer                   :: temp       ! Temporary variable

! Get the name of the file containing the input data
write (*,*) 'Enter the file name with the data to be sorted'
read (*,'(A20)') filename

! Open input data file
Open (Unit=9, file=filename, status='OLD', action='read', &
      iostat=istat )

! Was the open succesful
fileopen: if ( istat == 0 ) then              ! Open succesful

  ! The file was opened succesfully, so read the data value 
  ! to sort, allocate a variable for it, and locate the proper
  ! point to insert the new value into the list

  input: do
    read (9, *, iostat=istat) temp            ! Get value
    if ( istat /=0 ) exit                     ! Exit on end of data
    nvals = nvals + 1                         ! Bump count

    allocate (ptr, STAT=istat)                ! Get value
    ptr%value = temp                          ! Store number

    ! Now find out where to put it in the list.
    new: if (.not. associated(head)) then     ! No values in list
      head => ptr                             ! Place at front
      tail => head                            ! Tail pts to new value
      nullify (ptr%next_value)                ! nullify next ptr
    else
      ! Values alreadd in list. Check for location.
      front: if ( ptr%value < head%value ) then
        ! Add at front of list
        ptr%next_value => head
        head => ptr
      else if ( ptr%value >= tail%value ) then
        ! Add at end of list
        tail%next_value => ptr
        tail => ptr
        nullify (tail%next_value)
      else
        ! Find place to add value
        ptr1 => head
        ptr2 => ptr1%next_value
        search: do
          if ( (ptr%value >= ptr1%value) .and. & 
              (ptr%value < ptr2%value) ) then
          ! Insert value here
          ptr%next_value => ptr2
          ptr1%next_value = ptr
          exit search
          end if
          ptr1 => ptr2
          ptr2 => ptr2%next_value
        end do search
      end if front
    end if new
  end do input

  ! WHERE I BELIEVE THE SEGMENTATION FAULT OCCURS
  ! Now write out the data. 
  ptr => head
  output: do
    if ( .not. associated(ptr) ) exit            ! Pointer valid?
    write (*, '(I10)')  ptr%value                ! Yes: Write value
    ptr => ptr%next_value                        ! Get next pointer
    deallocate(ptr, StAT=istat)
  end do output

else fileopen
  ! Else file open failed. Tell user.
  write (*, '(A,I6)') 'File open failed--status =', istat

end if fileopen

end program insertion_sort

















【问题讨论】:

  • 请使用 -g 重新编译以获取调试信息,以便显示更合理的回溯。
  • 当你遇到这些问题时,使用你的编译器有的所有调试标志。例如gfortran -g -Wall -fcheck=allifort -g -warn -check。众所周知,这些带有指针的代码很难推理,调试通常必须使用调试器和类似工具(例如 valgrind)来完成。不能只看回溯就看到错误。
  • 为什么在完成指针分配后释放PTR?也就是说,ptr =&gt; ptr%next_value ; deallocate(ptr, StAT=istat) 不可能是你想做的。
  • Fortran 中的指针可以是关联的、未关联的或未定义的。您不能将 ASSOCIATED 与未定义的指针一起使用。 head 变量的初始状态是什么?
  • 这一行也不能满足你的要求ptr1%next_value = ptr。普通赋值和指针赋值是有区别的。

标签: linked-list segmentation-fault fortran selection-sort


【解决方案1】:

只是为了跟进。我已经完成了代码,它现在可以工作了。通过在开始时使头指针无效来避免分段错误。之前的代码在其 if 语句中也存在问题,因为它之前没有考虑到最后一个或第一个数字是最高还是最低。

program insertion_sort
implicit none

! Derived data type to store integer values in 
type int_value
  real                      :: value
  type (int_value), pointer :: p
end type

! Data dictionary: declare variable types & definitions
type (int_value), pointer :: head => null()    ! Pointer to head of list
character(20)             :: filename          ! input data file name
integer                   :: istat             ! status: 0 for succes
integer                   :: nvals = 0, i = 0  ! Number of data read
type (int_value), pointer :: ptr               ! Ptr to new value
type (int_value), pointer :: ptr1              ! Temp ptr for search
type (int_value), pointer :: ptr2              ! Temp ptr for search
type (int_value), pointer :: tail              ! Pointer to tail of list
real                      :: temp              ! Temporary variable
character(80)             :: msg               ! I/O Message

! Get the name of the file containing the input data
write (*,*) 'Enter the file name with the data to be sorted'
read (*,'(A20)') filename

! Open input data file
Open (Unit=9, file=filename, status='OLD', action='read', &
      iostat=istat, iomsg=msg )

! Was the open succesful
fileopen: if ( istat == 0 ) then              ! Open succesful

  ! The file was opened succesfully, so read the data value 
  ! to sort, allocate a variable for it, and locate the proper
  ! point to insert the new value into the list

  input: do
    read (9, *, iostat=istat) temp            ! Get value
    if ( istat /=0 ) exit                     ! Exit on end of data
    nvals = nvals + 1                         ! Bump count

    allocate (ptr, STAT=istat)                ! Get value
    ptr%value = temp                          ! Store number

    ! Now find out where to put it in the list.
    new: if (.not. associated(head)) then     ! No values in list
      head => ptr                             ! Place at front
      tail => head                            ! Tail pts to new value
      nullify (ptr%p)                         ! nullify next ptr
    else
      ! Values alreadd in list. Check for location.
      front: if ( ptr%value <= head%value ) then
        ! Add at front of list
        ptr%p => head
        head => ptr
      else if ( ptr%value >= tail%value ) then
        ! Add at end of list
        tail%p => ptr
        tail => ptr
        nullify (tail%p)

      else
        ! Find place to add value
        ptr1 => head
        ptr2 => ptr1%p
        search: do
          if ( (ptr%value >= ptr1%value) .and. &
              (ptr%value <= ptr2%value) ) then
          ! Insert value here
          ptr%p => ptr2
          ptr1%p = ptr
          exit search
          end if
          ptr1 => ptr2
          ptr2 => ptr2%p
        end do search
      end if front
    end if new
  end do input

   !Now write out the data.
  ptr => head
  output: do
    if ( .not. associated(ptr) ) exit            ! Pointer valid?
    write (*, '(F10.4)')  ptr%value              ! Yes: Write value
    ptr => ptr%p                                 ! Get next pointer
  end do output

  deallocate(ptr,STAT=istat)

else fileopen
  ! Else file open failed. Tell user.
  write (*, '(A,I6)') 'File open failed--status =', istat

end if fileopen

end program insertion_sort


















【讨论】:

  • 强烈建议将派生类型中的所有指针组件默认无效。喜欢type (int_value), pointer :: p =&gt; null()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-04
  • 2021-07-01
  • 2021-04-30
  • 1970-01-01
相关资源
最近更新 更多