- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FIRST
Here is some code which is OK
module mod1
EXTERNAL bessel1
contains
subroutine bigfun(i1,i2)
integer :: i1
integer,value :: i2
print *,"bigfun"
call bessel1(16) ! literal
call bessel1(i1) ! dummy
call bessel1(i1+1) ! temporary
call bessel1(i2) ! dummy
end
end module mod1
!
!example external; (usually in another .f file, as is)
!Placed in this file to keep self-contained.
!
subroutine bessel1( i1 )
integer i1
print *,i1
end
When 'bigfun' is called, eg via:
subroutine example_main
use mod1
call bigfun( 17, 19 )
print *,"hellow"
end subroutine example_main
we get the expected output:
bigfun
16
17
18
19
hellow
SECOND
Here is some code which SEGFAULTS:
(everything else the same as the first example)
module mod1
EXTERNAL bessel1
contains
subroutine bigfun(i1,i2) bind(C)
integer :: i1
integer,value :: i2
print *,"bigfun"
call bessel1(16) ! literal
call bessel1(i1) ! dummy
call bessel1(i1+1) ! temporary
call bessel1(i2) ! dummy
end
end module mod1
Now, the output:
bigfun
16
17
18
Segmentation fault
My understanding of ISO Fortran
1. Use of 'EXTERNAL' statement to 'import' procedures is still supported
2. In which case: the interface of such an external procedure is 'implicit' , consisting of: a list of actual argument addresses is passed to the called procedure.
3. This implicit interface convention, the 'passing actual argument addresses', may require the complier to create temporaries, as we observe in the first (and second) example above, where the external procedure is CALLed using an integer literal, and an expression 'R-value', I1+1
4. Again, my reading is that the nature of the thing-being-passed the EXTERNAL procedure does not change the rule that implicit interface of an EXTERNAL-statement defined procedure is always a list of addresses (possibly via creation of temporaries if needed) .
Anyway, that is my take, which consistent with 'example1.f90', and with 'example2.f0' if example2.py is built using ifort.
The on difference between example1 and example2 is the addition of an (unused/irrelevant -- this is a pure Fortran program) attribute to the function (bigfun) within which the calls the the EXTERNAL-statement defined external procedure is made.
Two methods 'make the problem go away':
1. Both examples compile and run as expected via 'ifort'
2. Instead of using the EXTERNAL statement with it's implicit interface consisting of a list of addresses of its argument/dummies, an explicit interface definition is used to 'bring in' 'bessel' procedure into scope:
module mod1
!EXTERNAL bessel1
interface bessel1
subroutine bessel1(i1)
integer i1
end
interface i1
...
(as pointed out by jimdempseyatthecove)
Neither 1 nor 2 are _immediately_ available for me to follow (contact to the library provider would be necessary, or, to tear off a branch and make changes to thier source, but...)
Hence my question:
Is Intel sure that ifx is standard-conforming with respect to the behavior 'example2'?
I would expect to see a text in the standard going something like:
"The implicit interface to external procedures defined by an EXTERNAL statement consists of passing the addresses of the call arguments (via creation of implicit temporaries if necessary), UNLESS the call to the external procedure is being made from within a function:
1. for which the 'BIND(C)' attribute has been specified
2. AND for which one of its formal(dummy) arguments is given VALUE attribute
in which case, if such a containing-function argument appears in call to the external procedure defined by an EXTERNAL statement, then everything should be passed by address (via creation of temporaries if necessary) except for that one argument, which should have its value passed instead into the external procedure.
"
something like that? less wordy tho.
I couldn't locate words to this effect in WD 1539-1, J3/23-007r1 -- but i'm still reading.
Also curious if there are any explanatory code samples associated with the standard?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
On one of the other threads, they had a similar problem with external (reference verses value).
While I cannot confirm this, my assumption of the behavior is:
Procedures declared without BIND(C), external has Fortran argument passing (reference)
Procedures declared with BIND(C), external has C argument passing (value)
Somone can experiment with this to confirm the behavior.
Note, as with the other thread, replacing external with a proper interface resolves the issue.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
thank you for taking the time to respond
Ive paired the example down a bit, to exhibit:
1. why HOUSE1/2 calls to 'dog(16)' both succeed, with both ifort/ifx?
2. Obviously, both know how to box a 'value', and send this to 'dog'
3. However, for the Fortran function HOUSE2 which include BIND(C), ifx (but not ifort) fails to make the necessary adjustment to the incoming argument 'i2' when calling 'dog'.
Note this example has nothing to do with 'C'.
Thanks again
module mod1
external dog
contains
subroutine HOUSE1(i1,i2)
integer :: i1
integer,value :: i2
print *,"HOUSE1",i1,i2
call dog(16)
call dog(i1)
call dog(i1+1)
call dog(i2)
end
subroutine HOUSE2(i1,i2) BIND(C)
integer :: i1
integer,value :: i2
print *,"HOUSE2",i1,i2
call dog(16)
call dog(i1)
call dog(i1+1)
call dog(i2)
end
end module mod1
!!!!!!!!!!!!!!!
!EXTERNAL, veryold, f77 .so
!placed here to be self-contained
subroutine dog( i )
integer i
print *,"dog",i
end
!!!!!!!!!!!!!!!
program main
use mod1
call HOUSE1( 17, 19 )
call HOUSE2( 17, 19 )
print *,"hellow"
end program main
!
!ifx ifxBINDC.f90; a.out
!
! HOUSE1 17 19
! dog 16
! dog 17
! dog 18
! dog 19
!
! HOUSE2 17 19
! dog 16
! dog 17
! dog 18
! forrtl: severe (174): SIGSEGV, segmentation fault occurred
! Image PC Routine Line Source
! libpthread-2.17.s 00007F0B5B1E25D0 Unknown Unknown Unknown
! a.out 0000000000404F06 Unknown Unknown Unknown
! a.out 0000000000404F7E Unknown Unknown Unknown
! a.out 0000000000404A8D Unknown Unknown Unknown
! libc-2.17.so 00007F0B5AE283D5 __libc_start_main Unknown Unknown
! a.out 00000000004049B6 Unknown Unknown Unknown
!
!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In HOUSE2, the first three calls are properly passing by reference, whereas the forth call, using an attributed value dummy i2, is apparently passing by value. This is definitely a bug.
Will replacing the "external dog" with a proper interface correct the problem
!dir$ if(.false.)
external dog
!dir$ else
interface
subroutine dog(i)
integer i
end subroutine dog
end interface
!dir$ endif
(untested code)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It certainly does.
However, this requires me to modify (someone else's) original source, in the following:
1. go through the old f90's, remove the 'external dog' lines
2. add a 'use f77prototypes' to those files
3. Now, the hard part, look through the old old .f files, fixed width fortran files.
a) extract only the 'argument' type definitions from the function bodies
b) there is extensive use of '*' line continuation -- fix that, change to & for f90
c) dump these parts into a 'f77prototypes.f90'
I kinda hate doing that kinda thing tho (doesnt everyone?)
The original author(s) of the code had, i think, a not bad solution to grafting a C-interface onto the oldold .f files.
They made a handful of higher level 'HOUSE2' functions, which each call 1 (or more: some business logic slipped into the f90 layer) of the oldold.f functions
I don't really mind doing 1,2,3 outlined above; but it does kindof rile me that I'm only doing it because of a bug in 'ifx'. which might be temporary.
The author is Elizabeth Wong, and you can see this middle layer, there:
https://github.com/snopt/snopt-interface/blob/master/src/sqopt_wrapper.f90
In general, the underlying, oldold.f code is not available (this is the UcSD/Stanford optimization library SNOPT.
We have paid for that source -- so that i do know what the 'correct' interface definition should be (the 1-2-3 method above).
But that's cheating!
And without that source, i would have to infer the 'interface' from the usage in the 'sqopt_wrapper.f90' shim -- ugh!
Elizabeth Wong's method, using EXTERNAL, was sufficient to graft a subset of oldold.f Fortran source.
Now we have to break that division, because ... ifx has a bug?
c'mon.
Thank's for interest so far...
What I've done is collect
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you remove (comment out) the external
then add the options gen-interfaces and warn-interfaces, this may do the work for you.
Also, if you add the option of fpp .AND. define macros for external and EXTERNAL to substitute "!" this might comment out the external statement without editing the source.
Note, the gen/warn-interface may generate errors relating to misuse in calling conventions.
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