Fortran Call Troubleshooting: Passing Integers & Strings

  • Context: Fortran 
  • Thread starter Thread starter stupify
  • Start date Start date
  • Tags Tags
    Fortran
Click For Summary

Discussion Overview

The discussion revolves around troubleshooting issues related to passing integers and strings in Fortran subroutine calls, particularly focusing on the behavior of newer compilers compared to older ones. Participants explore the implications of Fortran's call-by-reference mechanism and its effects on legacy code.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Conceptual clarification

Main Points Raised

  • One participant notes that the new compiler seems inconsistent in passing integer values and strings, specifically mentioning that the integer 0 does not appear to be passed correctly to the subroutine.
  • Another participant questions the legality of the call statement with a numeric literal, suggesting that Fortran's call-by-reference paradigm means that the literal value 0 has no address to pass.
  • A different participant recalls experiences with older Fortran versions where numeric literals were passed by reference, leading to unexpected behavior when subroutines modified these literals.
  • Some participants discuss the possibility that the new compiler may handle passing differently than older compilers, with one suggesting that a compiler switch might resolve the issue.
  • One participant describes their experience with a specific Fortran compiler that creates a temporary variable for numeric literals during subroutine calls, which allows the expected behavior to occur.
  • There is a question about the syntax of character declarations in Fortran, specifically regarding the use of the extra '*' in the declaration of character variables.

Areas of Agreement / Disagreement

Participants express differing views on the behavior of numeric literals in subroutine calls, with some recalling past experiences that contradict the current understanding of the call-by-reference mechanism. The discussion remains unresolved regarding the specific behavior of the new compiler compared to legacy systems.

Contextual Notes

Participants mention potential differences in compiler behavior and compatibility with legacy code, as well as the historical context of Fortran syntax that may contribute to confusion. There are references to compiler flags and data structure alignment that may affect how arguments are passed.

stupify
Messages
4
Reaction score
0
ok,

Been programing for awhile, come from a visual basic background.

We have a new server with newer compilers. Compiling with -f77 switch.

Seems the old software allowed passing of integers, and strings in a call statement. New compilers seems to be inconsistent in passing the values.Example:

call foo(0,'Hello','World')subroutine foo(x,a,b)
integer x
character*(*) a
character*(*) b

if(x.eq.1) then
print *, a
else
print *, b
end if

return
end

Seems to not pass integer 0 to variable x.

Any thoughts. I have read that fortran passes by reference, not value; maybe someone can explain this to me.

Thnkx
 
Technology news on Phys.org
No responses,

Let me ask the question, is the call statement legal?

call foo(0,'Hello','World')
 
stupify said:
No responses,

Let me ask the question, is the call statement legal?

call foo(0,'Hello','World')

According to this reference (http://www.physics.nau.edu/~bowman/PHY520/F77tutor/11_subprograms.html ), a tutorial on F77 out of Northern Arizona University, no.

Call-by-referenceFortran 77 uses the so-called call-by-reference paradigm. This means that instead of just passing the values of the function/subroutine arguments (call-by-value), the memory address of the arguments (pointers) are passed instead.

The literal value 0 has no address, so there's no address to pass in the subroutine call. I'm not sure how F77 stores string literals such as 'Hello', and 'World'. In C, which you didn't ask about, a string literal evaluates to the address of the first character in the string, but string literals are considered read-only.
 
That doesn't seem right. In the past using Fortran-Y I've called subroutines with numeric literals. Looking at the assem listing you could see that the compiler had assigned the numeric literal to a mem location and the address for the numeric literal was passed. The bad thing was that there was nothing preventing the subroutine from changing the numeric literal because it now had its address (ie call by reference) .

What happened to me was I called a subroutine which did that and my numeric 3 argument got changed everywhere to a different number because wherever the compiler saw a 3 it pointed it to the same memory location. From there very bizarre program results happened.

Perhaps the newer compilers have handled this problem better but still pass things by reference.
 
Thanks for responding.

Some of the code is passing to C, other subroutines are passing to Fortran. I have not witnessed the problem with code passed to C.

You are confirming what I believe, yet I have legacy Fortran code doing exactly as I have outlined. Further, I have legacy programmers telling me you can. Yet I read guides, exactly stating what you posted. The old servers seems to handle the case, new server no.

Some websites indicate passing by value was legal prior to F77; I believe the old server is using a very old compiler that may be backward compatible.

Perhaps there is a compiler switch I can use ?

Anyway, I am still open to comments.
 
another thing to look at is how the library code is built?

I recall there's a flag on gcc for byte packing but I can't remember the name. Basically for structures it placed each element on an even byte boundary (for faster memory fetching). We had to remember to do that same otherwise the alignment was off, arguments were skipped ...

http://en.wikipedia.org/wiki/Data_structure_alignment
 
In the Fortran implementations I've used, a call with a numeric literal would create a temporary variable and then pass its address. This temporary variable is created at run time as part of the call mechanism (rather than just assigning some address and initializing it once at load time).

So for example (with the g95 fortran compiler that I'm using) the following code correctly prints "Is zero" each iteration. This indicates that the memory reference is not just initialized once at load time. (Note that the subroutine changes n but this does not affect the literal value of the next call). This all seems pretty well behaved by my expectations. Personally I think that if your new compiler doesn't behave like this then it's buggy.

Code:
program test
implicit none
integer :: k
  do k = 1,3
    call testsub(0)
  end do

contains

subroutine testsub(n)
integer :: n
  if (n == 0) then
       print *,'Is zero'
  else
       print *,'Not zero'
  end if
  n = 1
end subroutine
end program test
 
Last edited:
BTW. I'm not a Fortran expert, so can anyone tell me the purpose of the extra '*' in declaration: character*(*) a.

I thought all that's needed there is: character(*) a, or if preferred then the more verbose: character (len = *) :: a
 
Last edited:
uart said:
BTW. I'm not a Fortran expert, so can anyone tell me the purpose of the extra '*' in declaration: character*(*) a.

The "old style" syntax (still supported in F90 etc) was CHARACTER*length A
where "length" is either an integer constant, or the three characters (*).

This is probably because of the historical vagaries of Fortran syntax. There are no "reserved words" in Fortran, so CHARACTER(*) could potentially be a variable named CHARACTER (which would be type REAL, by default!) that is an 1-D array with an unknown number of elements. There's a practical limit to how far compilers have to "read ahead" to figure out what things actually mean. The apparently redundant characters remove the ambiguity.

FWIW, this is probably also the reason why "new style" Fortran syntax overdoses on colons.
 
  • #10
stupify said:
No responses,

Around here, you need to wait longer than an hour and ten minutes before complaining about a lack of responses. :wink:

In fact, we have a rule here (click the Rules link at the top of any page) that you need to want at least 24 hours before "bumping" a thread. If Mark hadn't already responded to the post (and quoted it), I would have deleted it.
 
  • #11
Thanks for your responses.

I bumped it, after I noticed 6 views, with no responses. Thought I would rephrase the question.

As uart explained, place value in temporary variable, and pass the address is what I have believed in the past. Code misbehaves occasionally, I am a bit mystified.
 
  • #12
I agree with the OP in this case. I saw his second post as more of a clarification (or simplification) to the original question rather than straight out bumping his post. :smile:

stupify said:
Code misbehaves occasionally, I am a bit mystified.
Ok it's interesting that it's only occasionally misbehaving. Are saying that if you run some simple "test" code, similar to that which was posted above, that it mostly works but sometimes gives unexpected results. Or are you referring to a more complicated piece of code that sometimes gives unexpected results and you've tracked it down to (perhaps?) this situation?

AlephZero said:
The "old style" syntax (still supported in F90 etc) was CHARACTER*length A
Thanks AlephZero, that makes perfect sense now. :smile:
 
Last edited:

Similar threads

  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 59 ·
2
Replies
59
Views
12K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 11 ·
Replies
11
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 22 ·
Replies
22
Views
5K
  • · Replies 2 ·
Replies
2
Views
2K