fortran : trying to make a minimal stack datastructure

fortran, fortran2003, fortran90, fortran95, stack

Solution

A few minor problems

1) When PUSH exits, CURRENT disappears with it. You need something like

TYPE(ELEMENT_TYPE),POINTER       :: CURRENT
! INIT CURRENT
ALLOCATE(CURRENT)

2) Likewise when POP finishes, it needs to delete the data so

B4LASTIN => STACK%LASTIN%PREV
DEALLOCATE(STACK%LASTIN)
STACK%LASTIN => B4LASTIN

3) ASSOCIATED works but only if the pointers are initialized properly.

TYPE(STACK_TYPE) :: STACK1
STACK1%LASTIN => NULL()

And you should be ready to run.

Problem

A question about stacks on SO, finally! All my life has led me to this point. So I needed to incorporate some rather large custom datastructure I made into a stack. I decided to write a minimal stack structure consisting of one integer value only. Here it is - ``` MODULE STACK_MODULE IMPLICIT NONE TYPE ELEMENT_TYPE INTEGER(4) :: VAL TYPE(ELEMENT_TYPE), POINTER :: PREV END TYPE ELEMENT_TYPE TYPE STACK_TYPE INTEGER(4) :: SIZE=0 TYPE(ELEMENT_TYPE), POINTER :: LASTIN END TYPE STACK_TYPE CONTAINS SUBROUTINE PUSH(VAL_,STACK) IMPLICIT NONE INTEGER(4), INTENT(IN) :: VAL_ TYPE(STACK_TYPE), INTENT(INOUT) :: STACK TYPE(ELEMENT_TYPE),TARGET :: CURRENT ! INIT CURRENT CURRENT%VAL = VAL_ CURRENT%PREV => STACK%LASTIN ! ADD CURRENT TO STACK STACK%LASTIN => CURRENT STACK%SIZE = STACK%SIZE+1 RETURN END SUBROUTINE PUSH SUBROUTINE POP(STACK,VAL_) IMPLICIT NONE TYPE(STACK_TYPE), INTENT(INOUT) :: STACK INTEGER(4) , INTENT(OUT) :: VAL_ TYPE(ELEMENT_TYPE), POINTER :: B4LASTIN !WRITE TO VAL_ IF (ASSOCIATED(STACK%LASTIN)) THEN VAL_ = STACK%LASTIN%VAL !TAKE OUT THE LAST-IN ELEMENT B4LASTIN => STACK%LASTIN%PREV STACK%LASTIN => B4LASTIN STACK%SIZE = STACK%SIZE-1 ELSE IF (STACK%SIZE.NE.0) THEN PRINT*, STACK%SIZE STOP 'MISMATCH BETWEEN STACKSIZE AND POINTER: BAD BOOK KEEPING!' END IF END IF RETURN END SUBROUTINE POP END MODULE STACK_MODULE PROGRAM MAIN USE STACK_MODULE IMPLICIT NONE INTEGER(4) :: I,J TYPE(STACK_TYPE) :: STACK1 DO I = 1,10 CALL PUSH(I,STACK1) END DO DO WHILE (ASSOCIATED(STACK1%LASTIN)) CALL POP(STACK1,J) PRINT*, J END DO END PROGRAM ``` The result surprised me considerably! I had doubts about whether the `SIZE` counter would keep up .. but not this. ``` 10 -1076898780 1752444 -1219604480 1651076143 stderr Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0xB777FD63 #1 0xB77803F0 #2 0xB78713FF #3 0x8048666 in __stack_module_MOD_pop #4 0x80487A3 in MAIN__ at prog.f95:? ``` Any pointers (pauses while giggling uncontrollably) on where I went wrong? Here is the link to the code on IDEONE. EDIT: The IDEONE link now contains the updated version of the code, with the solution incorporated into it! Hope it can be reused as a generic template for stacks!

Original source