- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a program that I am working on in two different places on my computer. The programs are nearly identical. Here is excerpt:
PROGRAM TEST_EDCELL
INTEGER, PARAMETER :: LENGTH = 5
CHARACTER(20) :: PICKLIST(LENGTH)
... define PICKLIST(1) through PICKLIST(5)...
CALL EDCELL (IROW, ICOL, ...PICKLIST...RETURNCODE)
END PROGRAM
SUBROUTINE PICKLIST (IROW, ICOL, ...PICKLIST...RETURNCODE)
CHARACTER(*) :: PICKLIST(:)
...
PRINT *, PICKLIST
END SUBROUTINE
In the first location this program runs fine. In the second location it compiles and links without error, but gives a runtime error "Program execption-stack overflow" on the PRINT *, PICKLIST line. In the debugger watchlist, PICKLIST is identified as "Undefined pointer/array".
I cannot see any differences in the codes or the directory structure that could cause these differences. In both cases I am running 2011.10.325. I believe that all of the compiler and link switches are standard. Can you suggest where or how to look for the cause?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for this clarification John. I understand that when I use an assumed size array argument it is up to me to insure that in the subroutine I do not overwrite the size of the array or nasty things may happen; whereas in an assumed shape argument the compiler knows the sizes and takes care of it for me--as long as an interface is provided.
But I have trouble coming to grips with recommended practice. I have about 30 old F77 programs that I must upgrade. Many of these used assumed length arguments. Apparently this is still fine, but from my readings I concluded that the practice is now frowned upon and should be avoided, using instead assumed-shape arguments "due to the additional capabilities available." This is the only reason I had tried the CHARACTER(*)::PICKLIST(:) syntax. I didn't know that an explicit interface was required. I am alarmed to see that it works sometimes without an explicit interface, but when I move the source to another location on my computer, or hand the source off to someone else, then it may not work. IF IT CAN'T BE GUARANTEED TO WORK WITHOUT AN EXPLICIT INTERFACE, THEN WHY DOESN'T THE COMPILER GIVE AN ERROR! I would have straightened out much earlier if it did.
What I read about obsolescent, obsolete, deleted, and recommended practice on this matter is quite confusing. Is there any good reason why I should not continue to use assumed-size array arguments, especially on existing programs where they already exist and have demonstrated bug-free use for many years?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I didn't pass a procedure as an argument and then call it from another routine (I don't even know how to do that). Here is a simple test program:
Program AssumedSizeArgument
! Testing for the legality of passing an assumed-shape array without an interface.
Implicit none
integer:: ia(5)
integer:: i
do i = 1, 5
ia(i) = i
end do
call sub (ia)
end program
Subroutine sub (ia)
integer :: ia(:)
print *, ia
end subroutine
When I compile this, provided I have the default show all warnings on (/warn:all), then I will get a warning about the lack of an interface. But if the program and the subroutine are in two separate files, no warning is given. (I don't know about the "check routine interfaces" option, where is it set?) Depending on environment, sometime the program builds and executes OK, sometimes it builds but gives a runtime error, and dometimes it fails to link.
After investigating this at some length it seems to me that the lack of an interface definitely lies outside the F90+ rules. Why doesn't the compiler show an error, or even a warning if the subroutine is in a different file from the calling program (as is very often the case, especially if it is in a library)?
(Also: how do I get a program sample or fragment pasted into this window and have it nicely formatted?)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Imagine in the case that the two program units are in different files, that subroutine sub is compiled a week later than the main program, by a different person, on a different machine. Until the subroutine is compiled the compiler doesn't know that the main program is in error. Given the way Fortran processors are typically implemented the only way that the error can be discovered is by some link time magic (that step could possibly take place a week later still, by a third person, on a third machine!). This is not so easy to arrange - the linker is typically language agnostic.
(Perhaps procedures that required an explicit interface in the calling scope could have their linker name mangled differently (?), but the resulting error message is not likely to be all that illuminating for users anyway.)
If assumed size works for you, then leave it alone. The main reason for moving away from assumed size in my mind is that the syntax for using
the rather handy array operations that F90 onward provide becomes more convoluted if you want to use those in any modifications that you subsequently do. But assumed size arguments are not formally obsolete and there are some use cases where they are still required in new code.
(Why is your dummy argument assumed size versus explicit size? If the answer is "I don't know the size of the array in the calling scope", then you can't use explicit shape, or assumed shape for that matter.)
(Outside of those use cases I always prefer assumed shape to assumed size (or explicit size even) in new code, indeed in many instances my new code uses features that exclude assumed size, so the preference is moot.)
Opinionated babble following: of more concern from a style/practice point of view to me would be that you have procedures being invoked that don't have an explicit interface, regardless of whether they are using F90 argument capabilities or not. In the absence of some select reasons to the contrary all your procedures should be internal procedures or module procedures. If I was actively maintaining a code base then fixing that would be much, much higher in priority than switching from assumed size to assumed shape.
(Assumed length character functions referred to above are a different beastie - they are obsolete and rather evil, but as part of moving all procedures into modules you would need to eliminate them anyway.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After investigating this at some length it seems to me that the lack of an interface definitely lies outside the F90+ rules.What? Your program does not provide a required interface, and according to the Fortran standard the program is in error. There is nothing "outside the ..rules" here.
Why doesn't the compiler show an error, or even a warning if the subroutine is in a different file from the calling program (as is very often the case, especially if it is in a library)?Programmers are good at deceiving the compiler. If the compiler has not been shown the declaration of the subroutine, it cannot know whether the argument passed to the subroutine is assumed size or assumed shape. Fortran 77 and earlier had only assumed size, so the compiler defaults to "assumed size" if you do not give it the necessary information regarding assumed shape arrays. If the called subroutine is in a library, neither the compiler nor you can know whether the argument is assumed shape or assumed size -- that information has to come from source code, correctly written documentation or a module file.
A compiler is not required to detect all programmer errors. Even when some types of error checking are possible, there is an associated cost to that checking and in practice only limited (if any) checking is compiled into production code.
Why does your buggy code "work" sometimes? Most commonly, for an assumed shape array argument a descriptor is passed. Often (this is implementation-dependent) the first member of the descriptor is the address of the array, following which there can be information about size, upper and lower bounds, etc. If the subroutine uses only the array, and none of the other items, it picks up the correct address and may work "correctly". However, the program is still in error and you are required to remove the error, lest you encounter catastrophic failure of your application when using a different compiler, different compiler switches, different OS, etc.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks everyone for their comments. Let me try to clarify some things.
I am well aware of the traditional F77 technique of passing the length of the array argument as an accompanying argument. I do that wherevery possible. Sometimes it is not, or at least very inconvenient. I am also well aware of the benefits of internal procedures and modules in this matter. Sometimes they just have to be external.
As to mecej4's discussion of not being able to tell an assumed size array from an assumed length, I thought it was in the declaration syntax: a(*) means assumed size and a(:) means assumed shape.
We could probably go on and on about good vs. bad practice, but that's not what I'm questioning here. The simple demo program I gave was only to illustrate the error/warning behavior of the compiler.
But I think I now understand that the compiler is simply unable to detect whether the calling routine provided an explicit interface or not, so it cannot report an error. However, when compiling an external subroutine with a dummary array declared a(:), it should know that an interface is required, however, and it would be "nice" if it gave a warning to that effect. When it sees the dummy array declared a(*) it should know that an explicit interface is not required, so no warning would be expected. In my case a small clan of programmers struggled with the development of a library subroutine in which the original coder carelessly assumed he should change the orginal (*) syntax to the new (:) syntax, and he distributed it to others that way for testing and further development. For everyone the compiler always reported "0 errors 0 warnings." Sometimes the resulting program would work and sometimes it would not, causing a range of problems from linker errors to runtime. This set us back a couple of weeks in understanding the problem. A compiler warning would have led us to it almost immediately.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
John Campbell wrote:
Ian's position of "Assumed length character functions referred to above are a different beastie - they are obsolete and rather evil" looks to be a bit extreme and baseless to me.
Perhaps - but while the "evil" bit is certainly just a matter of my opinion, their obsolescense is a matter of fact. Do you actually use them? They are pretty bizarre.
(I think they only got introduced into the thread because of a naming error in the initial example?)
I agree that duplicating the source declaration of a procedure is error prone - which is why you only do it when you absolutely have to and use modules for everything else (and if you are using modules, I think the language rules say you can't use assumed length character functions, but perhaps I'm hallucinating from the heat again).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Could you elaborate how you think some sort of new calling convention would fix the issue?
Upthread I was thinking that any external procedure that used language features that required an explicit interface (bar BIND(C)) could have something like "$dear_programmer_you_forgot_to_provide_an_explicit_interface" appended to its linker name. In the calling scope the compiler in the absence of an interface block would generate the the wrong name (nothing appended) for the reference. If there was an explicit interface available in the calling scope the compiler could use that to determine whether the procedure met the criteria of requiring an explicit interface and then generate the appropriate linker name. Fortran-fortran libraries that used the affected procedures would need to be recompiled (or the additional mangling suppressed by compiler switch), but I'd expect the number of use cases of people "interfacing" outside of Fortran with the sort of procedure that would have its linker name mangled in such a way would be small.
A warning that I think would be more useful than the one dboggs suggested ("external procedure using language features that requrie an explicit interface be accessible where the procedure is invoked") would be to warn when the compiler sees any procedure without an explicit interface. I think that's been discussed here recently. Other compilers I use do this.
(I appreciate that you would want to be able to control this warning as it would drive you nuts when compiling old code (in the same manner as warning about implicit typing), but in large modern code bases where all procedures have explicit interfaces it similarly drives me nuts to have to wait around for the link stage in order to find out that you mispelled some procedure call early on in the compile.)
As you say - the issue is that the compiler needs to have explicit knowledge about the nature of some called procedures at the time that it encounters the calls. I disagree, though, that the language has failed to solve this robustly - as the use of modules guarantees that the compiler explicitly has this information - the compiler must have seen the definition of the module prior to its point of use. If you are required to use interface blocks to provide that explicit knowledge to the compiler (explicit interfaces) in clean-slate modern Fortran code today it is typically (always?) because you as a programmer cannot practically arrange for the definition of the procedure to be fed to the Fortran compiler before the call, perhaps because of some circular dependency, or an impractically large source base, or because the called procedure isn't written in Fortran. If you are not using the available robust solution (modules) because of a legacy code base, then I think all other solutions to the problem would similarly be not available.
(The existance of valid reasons in the rules of the language (independent of style) for being forced to use interface blocks for procedures that require an explicit interface be available in the calling scope is one of the reasons why I'm not so keen on dbogg's suggested warning message (don't warn me about something that the language is forcing me to do in new code). While always having an interface available is a practice/style issue, I don't think there is anything in the language rules that prevent you from always providing such an interface in new code (you can fix your code to avoid the warning).)
(If your two example calls are in response to me they both involve assumed length character arguments (very much on my "good" list), not assumed length character functions ("evil", more so than statement functions even...).)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We appear to have disparate views on the benefits/dangers of using assumed-shape array arguments (and, for similar reasons, optional and allocatable arguments). Please permit me to state a pragmatic point of view.
Assume that we wish to access subprograms which, according to the Fortran standard, require an explicit interface, and are part of a pre-compiled library or DLL; we want to write code with calls to those subprograms.
(i) If we have module files containing, among other things, the required interfaces, we should include the appropriate USE statements in our code. The compiler can then warn if our calls do not adhere to the interface. This is the approach used in commercial libraries such as IMSL and MKL.
(ii) If we wish to use a library as in (i) but do not have the module files, or the module files are not compatible with our Fortran compiler, we need to write INTERFACE blocks or modules containing interfaces by consulting the documentation of the library routines, and make these interfaces available in each caller.
(iii) If we are unable to provide the required interfaces, we should not link against the library, because the resulting code will probably be unstable and error-prone, and the compiler cannot give any warnings or run-time errors related to the missing interfaces.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page