Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29246 Discussions

Memory access problem with ancient code

dwarning
Beginner
2,269 Views

I try to restore an old legacy code from the 70th. I know it is not standard conform anymore.

The strong reduced shown code, compiled with ifx -g -O0 test_entry.for -o test_entry

brings an memory access violation in line 33. From gdb I got:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004054aa in me$laslas_ (khh=..., mhh=<optimized out>, das=<optimized out>, 
    ix=<optimized out>) at test_entry.for:33
33	         Ix = n/2

Same result for gfortran: Variable Ix can't accessed.

Is it possible to fix the problem by compiler switches or different declarations without to change the entire program structure, e.g. splitting the multiple entry subroutine in separated pieces?

      PROGRAM NAP2

      CALL FILIN

      END

      SUBROUTINE filin

      CALL lasa

      CALL name('* Q*. ',3,*52,*46)

 46   CONTINUE
 52   CONTINUE

      END

      SUBROUTINE laslas(Khh,Mhh,Das,Ix)
      IMPLICIT REAL*8(A-H,O-Z)
      INTEGER*2 Khh(Mhh)
      INTEGER Mhh, Ix
      REAL*8 Das

      ENTRY lasa

      RETURN

      ENTRY name(Khh,Mhh,*,*)

      n = 2

      IF ( n.LE.8 ) THEN
         Ix = n/2
         RETURN 1
      ENDIF

      RETURN 2

      END

 

0 Kudos
17 Replies
JohnNichols
Valued Contributor III
2,225 Views

The program will not compile in the latest IFX with the latest VS preview.  

See below.  Line 11 throws an error not a code fault. 

Screenshot 2025-05-17 070651.png

0 Kudos
JohnNichols
Valued Contributor III
2,224 Views

Debugging code like this will be a nightmare, if it is more than a few hundred lines, good hunting.

0 Kudos
dwarning
Beginner
2,193 Views

Thanks for answering.

My version onlinux is quite new:

ifx version 2025.1.1

 

And substituting the FILIN subroutine with:

      SUBROUTINE filin
      INTEGER*2 Khh(3)

      CALL lasa

      CALL name(Khh,3,*52,*46)

 46   CONTINUE
 52   CONTINUE

      END

brings same error.

The scope of the declared variables and dummy arguments seems lost in the ENTRY parts.

 

I aggree that the code is not best practice. gfortran needs extra switch -fallow-argument-mismatch to accept the chars.

0 Kudos
andrew_4619
Honored Contributor III
2,154 Views

From 40 years of fortranning I have no idea what *52 and *46 as values mean and the compiler thinks the same. What you are asking is that the compiler guess what the non standard interpretation of some code was in an ancient compiler and do the same thing. IMO you have some serious refactoring to do or if that is too much throw it in the bin and go on holiday instead and have some beers. I am sorry I cannot help. 

0 Kudos
GVautier
New Contributor III
2,148 Views

*52 and $46 are labels for alternate return

return 1 returns to label 52

return 2 returns to label 46

...

It's a legacy fortran standard feature  becoming obsolescent in Fortran 95

https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2025-0/alternate-return-arguments.html

 

0 Kudos
JohnNichols
Valued Contributor III
2,131 Views

It is not deleted Fortran and IFX did not object.  The real problem is the implicit and the declaration of variables.

If you have the energy, the stultitia and the time, then the first thing is to fix all the variables and discover the numerous errors in variable naming like  name and nane, which may look alright but it not what is intended. 

It is very old Fortran and like Old English it can be hard to understand. 

 

    PROGRAM NAP2
    implicit none
    character*7 ACD

    ACD = '* Q*. '
    CALL FILIN(ACD)

    END

    SUBROUTINE filin(ACD)
    implicit none
    integer IX

    character*7 ACD
    Write(*,*)ACD
    CALL lasa(3)

    CALL name(ACD,3,IX,*52,*46)

46  Write(*,*)"At 46"
    return
52  Write(*,*)"At 52"
    return
    END

    SUBROUTINE laslas(Khh,Mhh,Das,Ix)
    IMPLICIT none
    INTEGER*2 Khh(Mhh)
    INTEGER Mhh, Ix
    REAL*8 Das
    character*7 ACD
    integer n

    ENTRY lasa(IX)
    write(*,*)"At lasa", IX
    RETURN

    ENTRY name(ACD,Mhh,IX,*,*)
    write(*,*)"Name"
    n = 2

    IF ( n.LE.8 ) THEN
        Ix = n/2
        RETURN 1
    ENDIF

    RETURN 2

    END

 

 

It is not hard to fix, about 20 minutes work, but you have to start with implicit none and if you call name, then if you do not pass IX to name it cannot see it, and no I do not know why, I just write the code I am not Steve.  

0 Kudos
JohnNichols
Valued Contributor III
2,131 Views

In the Filipino language, "laslas" primarily means "to cut" or "to slash," often referring to a deep cut made with a sharp object. It can also be used more metaphorically to describe budget cuts or other "cuts" in a broader sense. The word originates from the root "las," implying a cut or incision. 

0 Kudos
andrew_4619
Honored Contributor III
2,059 Views
Yes now you mention alternative return I have seen that, but the problems with this code run deeper. I guess when you write a new compiler from scratch mixes of non standard and obsolete code are more likely to fall through holes in testing and will not be a high priority in the allocation of resources for fixing things. As noted below is seems strange that some things ever compiled ok but I have seen many examples of code errors that worked because the compiler did not see the error and the result happened to be what the coder expected so it was deemed good code. Without validated results from the old compiler it can be hard to fix.
0 Kudos
GVautier
New Contributor III
2,129 Views

The problem is to know if that code has ever been successfully compiled in that state.

For me the sentence

 ENTRY name(Khh,Mhh,*,*)

is invalid because ix is not referenced in arguments so where can the compiler returns the value?

0 Kudos
JohnNichols
Valued Contributor III
2,078 Views
ENTRY name(ACD,Mhh,IX,*,*)

if I do not put IX in the arguments, then line 43 cannot see the IX declared in the subroutine at the subroutine level and it crashes. 

Screenshot 2025-05-17 150015.png

From my write statements it appears to run ok.  

No one has written code like this since the 1970s, but knowing how to fix it is important,  I actually think the return1 etc is neat.  

0 Kudos
dwarning
Beginner
2,059 Views

@JohnNicholsthank you. Yes include IX in the argument list of name() makes the trick. I will try it but I am afraid that there a lot of further variables to consider. Because my test case is only a reduced excerpt.

It is curious for me that IX is not seen in ENTRY name() even it is declared in the subroutine.

Perhaps is split the code in separate subroutines.

0 Kudos
JohnNichols
Valued Contributor III
1,964 Views

@andrew_4619 , it is unlikely that anyone would use this code unless it was unique and the cost to create from new was higher than a fix. 

Sometimes it is better to fix the old, where it is a rare bit of code, it is short and the need is high. Usually the code is sitting in some thesis and it has not been used past the research.  @mecej4  helped me wonderfully with Harrison's 72 code, I learnt a lot of useful things to drive structural reliability analysis forward.  We have not heard from him in six months, I hope he is ok. 

Without doubt the best FEM code is ULARC, but it is for special structural uses, but for those at the leading bleeding edge of the reliability analysis you cannot find better or equivalent. 

The 1960's team at UCB were really good in structures, their Drain program has been an academic favourite for years, it is just limited.  There is no duplicate to Powell's group anywhere in structures. 

I was standing on a major bridge over the Mississippi River discussing the Ularc analysis with a state engineer,  when you need good code you really need it.  

I have about 100 million database records from accelerometers in several mySQL tables.  I thought I had trapped in code all of the versions that the date and time could take as output from mysql and I just found a new one, after 8 years. 

Fortran is fun, because it is fast and this forum is the best. 

 

 

0 Kudos
GVautier
New Contributor III
1,890 Views

From the documentation :

"There can be any number of alternate returns in a subroutine argument list, and they can be in any position in the list."

So the position of IX is not relevant.

Effectively, the old compilers often fail to detect coding errors unlike newer ones but produce apparently functional programs.

But before all, correct the test code by adding Ix in name entry and call.

      CALL name('* Q*. ',3,Ix,*52,*46)
...
      ENTRY name(ACD,Mhh,Ix,*,*)

 

0 Kudos
JohnNichols
Valued Contributor III
1,837 Views

There is no relevance to any of the positions as long as there is a 1 to 1 correspondence in name call and subroutine or entry

But Fortran cannot see a variable passed in the subroutine after the entry statement, so you may as well have separate subroutines.

This is the beauty of Lisp, you start out with built in commands that are a strange language and then you write programs that are almost plain English and easy to follow, unless you like to make it difficult to read and debug. 

 

An example of a program that is easy to write is a Hardy Cross - pipe analysis program, it is very hard to scale, almost impossible actually, but it is theoretically sound.  But saying the code is correct at scale is impossible as you cannot get solutions that converge in a reasonable time.  I know I have tried. 

0 Kudos
dwarning
Beginner
1,816 Views

Found this fruitful discussion here:

Runtime-issues-in-legacy-multiple-entry-subroutines 

Because the argument list extension would be too large, I want try to transfer the these variables per common block.

Thank you to all!

0 Kudos
JohnNichols
Valued Contributor III
1,800 Views

There is one really great programmer on this forum, the discussion you showed had the best explanations from @mecej4 , there are also great programmers, but he is the best.  Personal opinion and I am poor programmer. 

I am sure that he would tell you that common blocks are a big no.  

We see common blocks slipping back into c# and it is annoying.  With another name, but an apple in the UK and apfel in Germany  is still mainly red and good for you, not so common blocks. 

Use types as @mecej4 showed me for old code from the 70's.  I include samples. It is worth the effort. 

!---------------------------------------------------------------------------------------------------------------------------
    !
    !   Real variables
    !
    !---------------------------------------------------------------------------------------------------------------------------

    REAL                time(2)         !   Holds the numbers for the run time calculation

    !---------------------------------------------------------------------------------------------------------------------------
    !
    !   Type variables  model holds the overall model data and Triangle holds data for each triangular element
    !
    !---------------------------------------------------------------------------------------------------------------------------

    TYPE (Model),       TARGET :: ModelA                            !   Model for the FEM
    TYPE (Triangle),    allocatable,   TARGET :: sTriShells(:)      !   Each triangle that makes up the FEM model
    TYPE (sbeam),       allocatable,   TARGET :: sBeams(:)
    TYPE (aBeam),       allocatable,   TARGET :: saBeams(:)      !   Each triangle that makes up the FEM model

    !---------------------------------------------------------------------------------------------------------------------------
    !
    !   Routine opens the files used for data input and output
    !   Base is the ultimate lowest module to allocate the file numbers, si, sw, sa, slog
    !
    !---------------------------------------------------------------------------------------------------------------------------
    call Files(1)
    !call OpenFiles(si,sw,sa,slog,srA)                  Not used at this stage

    !---------------------------------------------------------------------------------------------------------------------------
    !
    !   Saves the start time for the analysis time estimate
    !
    !---------------------------------------------------------------------------------------------------------------------------

    CALL cpu_time(time(1))

    !---------------------------------------------------------------------------------------------------------------------------
    !
    !   Set up the model type used to hold the main details of the overall model
    !
    !---------------------------------------------------------------------------------------------------------------------------

    Call SetModel(ModelA, Triangles, BeamNum)

    !---------------------------------------------------------------------------------------------------------------------------
    !
    !   Allocate memory for the triangular elements
    !
    !---------------------------------------------------------------------------------------------------------------------------

    ALLOCATE (sTriShells(Triangles), ModelA%indexM(3,ModelA%MaxNodeNumber), ModelA%nodes(ModelA%MaxNodeNumber),ModelA%offsetnodes(ModelA%MaxNodeNumber),ModelA%nodeloads(ModelA%MaxNodeNumber,6), ModelA%nodeWeight(ModelA%MaxNodeNumber),sBeams(NTA), saBeams(Beamnum), STAT=astat)

    IF (astat.NE.0) then
        STOP 'Could not allocate Shells or Model'
    endif
    Beams = Zero
    CAll ReadBeams(Beams, sBeams, Triangles)
    ModelA%SK = ZERO               !   Zero the Stiffness Matrix
    ModelA%nodes = -1               !   Set the node numbers to -1 so they can be counted
    ModelA%nodeloads = ZERO
    !---------------------------------------------------------------------------------------------------------------------------
    !
    !   Read in the data for each triangular element from the si input file
    !
    !---------------------------------------------------------------------------------------------------------------------------

    Do I = 1,Triangles
        Call Read_Triangles(sTrishells(I))
        call setRestraints(sTrishells(I)%restraint, sTrishells(I)%nodes, ModelA%nodes)
    end do

    Do I = 1, Beamnum
        call Read_Beams(saBeams(I), sBeams, I)
        call setRestraintsB(saBeams(I)%restraint, saBeams(I)%nodes, ModelA%nodes)
    end do

    Call CountNodes(ModelA%nodes, ModelA%N, ModelA%NodeCount, ModelA%MaxNodeNumber,ModelA%LoadedNodes, ModelA%nodeloads)

    ALLOCATE (ModelA%SK(ModelA%N,ModelA%N),ModelA%XF(ModelA%N),ModelA%LoadXYZ(ModelA%N), ModelA%nodemass(ModelA%N,ModelA%N),STAT=astat)
    IF (astat.NE.0) then
        STOP 'Could not allocate SK or XF'
    endif
    ModelA%SK = ZERO
    Call SetLoad(ModelA%nodeloads,ModelA%loadxyz, ModelA%nodes, ModelA%MaxNodeNumber,ModelA%N)

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,554 Views

>>I want try to transfer the these variables per common block.

I would suggest that you use a module instead of common block.

The use of common block may present issues down the road (name collisions and/or omission of variable names/types).

Jim Dempsey

 

0 Kudos
Reply