- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I'm trying to call the open statement with some specifiers which are non-associated pointer variable.
Since the specifier in the open statement are optional arguments, calling the open statement with a non-associated pointer argument should be the same as if this optional argument were not specified.
However, I'm getting a segmentation fault with the following code.
Program Main
implicit none
integer :: Unit
integer :: ios
character(*) ,parameter :: FileName = 'formatted.dat'
character(4) ,target :: Open_Action
character(4) ,pointer :: Open_Action_Pointer
! *********************************************************************
Open_Action = 'read'
write(*,"('Open_Action = ',g0)") Open_Action
open( NewUnit=Unit, File=FileName, Action=Open_Action, IOStat=ios ) ! -> OK
write(*,"('open ios = ',g0)") ios
! *********************************************************************
Open_Action_Pointer => Open_Action
write(*,"('associated(Open_Action_Pointer) = ',g0)") associated(Open_Action_Pointer)
if (associated(Open_Action_Pointer)) write(*,"('Open_Action_Pointer = ',g0)") Open_Action_Pointer
open( NewUnit=Unit, File=FileName, Action=Open_Action_Pointer, IOStat=ios ) ! -> OK
write(*,"('open ios = ',g0)") ios
! *********************************************************************
Open_Action_Pointer => null()
write(*,"('associated(Open_Action_Pointer) = ',g0)") associated(Open_Action_Pointer)
if (associated(Open_Action_Pointer)) write(*,"('Open_Action_Pointer = ',g0)") Open_Action_Pointer
open( NewUnit=Unit, File=FileName, Action=Open_Action_Pointer, IOStat=ios ) ! -> DOES NOT WORK
write(*,"('open ios = ',g0)") ios
! *********************************************************************
End Program
Note that you have to create in the local directory a file called "formatted.dat":
touch formatted.dat
The above code produces the following output
ifort main.f90; ./a.out Open_Action = read open ios = 0 associated(Open_Action_Pointer) = T Open_Action_Pointer = read open ios = 0 associated(Open_Action_Pointer) = F forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source a.out 00000000004674D9 Unknown Unknown Unknown a.out 0000000000465DAE Unknown Unknown Unknown a.out 0000000000443D52 Unknown Unknown Unknown a.out 000000000042DCC3 Unknown Unknown Unknown a.out 000000000040329B Unknown Unknown Unknown libpthread.so.0 00002B99B8665750 Unknown Unknown Unknown a.out 000000000040837F Unknown Unknown Unknown a.out 0000000000402FC9 Unknown Unknown Unknown a.out 0000000000402C96 Unknown Unknown Unknown libc.so.6 00002B99B8894D65 Unknown Unknown Unknown a.out 0000000000402B89 Unknown Unknown Unknown
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
flying_hermes wrote:
Since the specifier in the open statement are optional arguments, calling the open statement with a non-associated pointer argument should be the same as if this optional argument were not specified.
Unless you can point to clauses in the Fortran standard to support this conjecture, I am inclined to think that it is not true.
If you have an optional argument present whose INTENT attribute is not OUT, the called routine (user written or intrinsic) would need to access the argument (by dereferencing, if appropriate) in order to decide what to do with it. This is probably the reason for the program to experience an access violation/seg-fault.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Per Jon Reid's "The New Feratures of Fortran 2008 document:
[plain]
A null pointer or unallocated allocatable that corresponds to an optional non-allocatable
non-pointer dummy argument is interpreted as an absent argument.
[/plain]
I believe such a feature has been available in Intel Fortran since version 14 - perhaps someone (Intel staff?) can verify. Which version of the compiler are you using?
However I don't know whether a non-associated pointer argument evaluates to a null pointer - seems to make sense, but again, it'll be useful if someone more knowledgeable about the 2008 standard can comment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Note that an OPEN statement doesn't have arguments (it isn't an "open procedure reference") - the things that might look like named arguments are specifiers, so I think discussion of the F2008 feature is moot.
"Null" in that context means a disassociated pointer(pointers either being associated, disassociated or undefined).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So, it there any way I can wrap the open statement in a procedure as in the following example
! ifort main.f90; ./a.out
Module File_Class
implicit none
Type :: File_Type
integer :: Unit
character(:) ,allocatable :: FileName
contains
procedure ,public :: Open => Open_File
End Type
contains
Subroutine Open_File( This, FileName, Action, Status, IOStat )
class(File_Type) ,intent(inout) :: This
character(*) ,intent(in) :: FileName
character(*) ,optional ,target,intent(in) :: Action
character(*) ,optional ,target,intent(in) :: Status
integer ,optional ,intent(out) :: IOStat
character(:) ,pointer :: Open_Action_Ptr
character(:) ,pointer :: Open_Status_Ptr
integer :: Open_IOStat
Open_Action_Ptr => null()
Open_Status_Ptr => null()
if ( present(Action) ) Open_Action_Ptr => Action
if ( present(Status) ) Open_Status_Ptr => Status
This%FileName = FileName
open( NewUnit = This%Unit, &
File = This%FileName, &
Action = Open_Action_Ptr, &
Status = Open_Status_Ptr, &
IOStat = Open_IOStat )
if ( present(IOStat) ) IOStat = Open_IOStat
End Subroutine
End Module
Program Main
use File_Class ,only: File_Type
implicit none
character(*) ,parameter :: FileName = 'formatted.dat'
type(File_Type) :: File
integer :: Open_IOStat
character(:) ,allocatable :: String
! =======================================================================================
! ==> THIS DOES NOT WORK FINE SINCE SOME OPTIONAL ARGUMENTS ARE NOT SPECIFIED <===
! =======================================================================================
String = "call File%Open( FileName, IOStat=Open_IOStat )"
write(*,"(/,a)") String
call File%Open( FileName, IOStat=Open_IOStat )
write(*,"('Open_IOStat = ',g0)") Open_IOStat
! =======================================================================================
! ==> THIS WORKS FINE SINCE ALL OPTIONAL ARGUMENTS ARE SPECIFIED <===
! =======================================================================================
write(*,"(/,a)") String
String = "call File%Open( FileName, Action='read', Status='old', IOStat=Open_IOStat )"
call File%Open( FileName, Action='read', Status='old', IOStat=Open_IOStat )
write(*,"('Open_IOStat = ',g0)") Open_IOStat
! =======================================================================================
! ===> THIS WORKS FINE, AS EXPECTED <===
! =======================================================================================
String = "open( NewUnit=File%Unit, File=FileName, Action='read', Status='old', IOStat=Open_IOStat )"
write(*,"(/,a)") String
open( NewUnit=File%Unit, File=FileName, Action='read', Status='old', IOStat=Open_IOStat )
write(*,"('Open_IOStat = ',g0)") Open_IOStat
! =======================================================================================
End Program
Of course, without having a deeply nested 'if' structure for each optional input argument.
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
While the good Doctor is away, I will inquire w/other Developers but it seems to me the program may be in error.
From the Fortran 2008 Standard, Section 9.5.6.2, (page 207, line 2) defines the specifier as “ACTION = scalar-default-char-expr” and on line 34 it says, “A specifier that requires a scalar-default-char-expr may have a limited list of character values. These values are listed for each such specifier. Any trailing blanks are ignored. The value specific is without regard to case.”
Further, in Section 9.5.6.4 (page 208, line 8) it says for the ACTION specifier, the "scalar-default-char-expr shall evaluate to READ, WRITE, or READWRITE."
With that and what IanH notes about "Null", it seems invalid in the context of ACTION specifier.
According to our Fortran UG, the default ACTION is "READWRITE", so in your code, for the case where that optional argument is not specified, you need to assign the pointer to refer to a valid default value instead of null(), which you could make different from the Intel compiler default. The STATUS specifier requires similar handling.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In your #5 code sample you are nullifying the local Open_Action_Ptr, and Open_Status_Ptr
Why not define your own defaults for Action and Status and then point the two pointers at either the defaults or the present() values as desired. In this way the OPEN statement will not have a null pointer.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is what I'm currently doing.
However, this approach quickly becomes very complex if I want to consider all possible specifiers of the open statement, that is: file, status, access, form, position, action, delim, blank, recl, pad and iostat.
In such case, there is no obvious default values for some specifier, since the default value of some specifier depend on the actual value of others. For example, if the "form" specifier is omitted, then then its default value is "form=formatted" for sequential access and "form=unformatted" for direct access, the access behavior being dictated by the "access" specifier.
In addition, some specifier should no be specified if other specifier have a given value. For example, if the specifier "access=direct" is present, then the specifier "position" must be omitted. Another example if that if the "file" specifier must not be present if the "status=scratch" specifier is considered.
Of course, this can be handle by nested "if" construct, but taking into account all possible cases make this approach rather complex.
On the other hand, if the "pointer" approach described above were to work, everything would be much more simple.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One Developer understood both points of view discussed in the thread, and while probably leaning towards the view these are optional keywords to a statement, they believed the run-time should have a better response than SegV for the NULL value so I submitted a request (see internal tracking id below) that the run-time protect against NULL-values provided and return an IOSTAT=0 for the case where the pointer association is False. I will keep you updated on the status of that as I learn it.
(Internal tracking id: DPD200358259)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Great news.
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is some further feedback/clarification from Development:
An OPEN statement is not a procedure call and the specifiers in an OPEN statement like ACTION= are not optional arguments. If the specifier is in the OPEN statement, the value of the specifier {the expression or variable after the =} is expected to exist if the value is needed to process the OPEN request. So pointers need to be associated and allocatables need to be allocated.
It is true that for procedure invocation, optional arguments can be not present if they are unassociated pointers or unallaocated allocatables. This is a feature of procedure invocation, not of statements that take keyword specifies like OPEN, CLOSE, and INQUIRE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
flying_hermes wrote:
This is what I'm currently doing.
Open_Action_Ptr => null() Open_Status_Ptr => null() if ( present(Action) ) Open_Action_Ptr => Action if ( present(Status) ) Open_Status_Ptr => Status This%FileName = FileName open( NewUnit = This%Unit, & File = This%FileName, & Action = Open_Action_Ptr, & Status = Open_Status_Ptr, & IOStat = Open_IOStat )
In the above, your code, you pass NULL() when arg not present, whereas:
Open_Action_Ptr => Default_Open_Action ! you define this Open_Status_Ptr => Default_Open_Status ! you define this if ( present(Action) ) Open_Action_Ptr => Action if ( present(Status) ) Open_Status_Ptr => Status This%FileName = FileName open( NewUnit = This%Unit, & File = This%FileName, & Action = Open_Action_Ptr, & Status = Open_Status_Ptr, & IOStat = Open_IOStat )
My recommendation does not pass a NULL() when arg not present.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Note, nothing precludes you from having different defaults for different Status (or lack thereof).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Kevin Davis (Intel) wrote:
Here is some further feedback/clarification from Development:
An OPEN statement is not a procedure call and the specifiers in an OPEN statement like ACTION= are not optional arguments. If the specifier is in the OPEN statement, the value of the specifier {the expression or variable after the =} is expected to exist if the value is needed to process the OPEN request. So pointers need to be associated and allocatables need to be allocated.
It is true that for procedure invocation, optional arguments can be not present if they are unassociated pointers or unallaocated allocatables. This is a feature of procedure invocation, not of statements that take keyword specifies like OPEN, CLOSE, and INQUIRE.
This is an issue that I ran into a while back as well, but using optional arguments instead of pointers and allocatables. IIRC, the same logic applies to optional arguments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe what you experienced/described Zaak is as one of our Developers describes it:
"If dummy arguments with the OPTIONAL attribute are supplied as inputs to keyword specifiers in the OPEN statement (and the like), they must be present (ie, the PRESENT intrinsic returns .TRUE.) and have a defined value; otherwise the program behavior is undefined."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Upon their further consideration/discussion and related to the subsequent clarifications that I posted, Development closed the earlier request DPD200358259 (regarding a better response than SegV) indicating the program behavior is undefined for the original (flying_hermes) case and the OPTIONAL case (Zaak) noted; therefore, no change will be made to the run-time behavior related to using non-associated pointers, non-allocated allocatables, or non-present/non-defined dummy arguments (declared with the OPTIONAL attribute) as inputs to keyword specifiers in OPEN (and the like) statements.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page