I have been trying to get rid of the warnings from my mixed Fortran and C++ solution, and one of them looked to be a no-brainer: a warning on the use of functions which are defined as CHARACTER(LEN=*).
I was paying particular attention to the https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/280657?language=en-us&https=1 thread (now closed), and all the contributors were quite set against CHARACTER(LEN=*) - although the reasoning wasn't overly clear.
My problem is that it works, and the stated alternatives don't. The function is QUOTESTR (you can probably guess what it does), and it accepts the argument accString:
CHARACTER(LEN=*) - This is some of our oldest code, and has produced the right answer for (literally) decades.
CHARACTER(LEN=:), ALLOCATABLE :: QUOTESTR - this causes a memory exception.
CHARACTER(LEN=2+LEN(accString)) :: QUOTESTR - This garbles the string completely. It is difficult to see in the debugger, but it looks like QUOTESTR is 2 long, whereas accString is 57.
The debugger flicks inbetween the code and the string declarations as you step, and I don't know if that's significant.
Why *are* CHARACTER(LEN=*) and CHARACTER*(*) a problem, and what should it be replaced by?
! needs /standard-semantics ! module thing implicit none contains function quoter(string) character(:), allocatable :: quoter character(len=*) :: string quoter ='"'//string//'"' end function quoter end module thing use thing, only: quoter character(:), allocatable :: fred fred =quoter('billy')
Do you know why this had caused a memory exception? I realise now that I hadn't changed the declarations of the function in the calling routines, e.g.:
Could this have meant that the function was getting conflicting definitions for the length of the string? And chose the worst combination of all possibilities? I'm prepared to write this off as user error (on my part), but it seems odd that I get a warning for something that fundamentally works, yet not even a note about something that causes a memory exception - one of the worst kind of runtime errors...
There are a number of situations where subprograms (subroutines and functions) are of such a nature that the Fortran standard (and the compiler) requires that an explicit interface be provided in the caller. In such situations, the implicit interface (which could be called the F77 and earlier interface) is not sufficient, and the compiler will most probably not generate correct code without the required interface. The Intel Fortran compiler can catch such incorrect usage if you use the /warn:interfaces option.
Many of the subprogram arguments that you described in this thread are of the type that make it necessary that an explicit interface be provided, and the run-time errors that you described are probably a result of failure to provide such an interface.
Declaring the function is not the right way you should have an explicit interface which is why I put it in a module and the the interface checking would then flag any error. How would the compiler know that the "quotstring" you declare is actually a reference to a function of the same name somewhere else?
I guess you would also get a link error if you had added the "external" attribute to the definition.
Thank you both.
I'm beginning to think that my Fortran learnt while on the job hasn't kept up with recent developments (say in the last 30 years since some of this code was originally written)!
Where I've seen the word "interface" being used in the past, it was for the explicit interface between a Fortran and a C function - so the interface is just that, and contains no code.
In @andrew_4619's example, the Fortran is declared within a module, and below the CONTAINS statement - does this in some way make it an interface, in spite of including all of the code as well? Our code is pretty much always structured thus:
And in another file or project:
integer function Y()
Is this just bad practice, and should all functions (and subroutines?) be defined in modules?
Steve Lionel (Intel) wrote:
Suggested reading: https://software.intel.com/en-us/blogs/2012/01/05/doctor-fortran-gets-ex...
I remember reading that useful article in the distant past. Maybe that needs a few tweaks now with the advent of submodules? or maybe just a sentence or two and a link to https://software.intel.com/en-us/blogs/2015/07/07/doctor-fortran-in-we-all-live-in-a-yellow-submodule
Thank you Steve - and everyone.
I had actually read that article - it was referenced in another of my queries. The trouble I find is that it assumes a lot of pre-knowledge, and doesn't actually conclude by giving any examples of the correct (or indeed incorrect) ways of doing things. For instance, the numbered points mention "pure" procedures, "assumed-shape array"s, "coarray", "parameterized derived type", "procedure is elemental", etc. - none of which I'm familiar with. I've been programming for 20 years now, but I admit that Fortran is about number 4 in my language-competence list. I had hoped that my reasonable knowledge of many other languages would help, but the jargon is completely different.
I've seen an example where the function is described thus:
CHARACTER ALLOCATABLE(LEN=:) FUNCTION do_something
CHARACTER ALLOCATABLE(LEN=:) do_something
Is this the correct practice? I hate asking such basic questions, but there doesn't appear to be a definitive source of knowledge for Fortran (maybe equivalent to www.cplusplus.com) but rather an infinite set of university hand-out notes, which describe a vast array of different Fortran versions and programming styles. For example, if I try to look up the definition for the CONTAINS keyword, then all of the top answers are for sites which end .edu or .ac.uk (the equivalent in the UK). The top hit (http://www.personal.psu.edu/jhm/f90/statements/contains.html) concentrates on the use of CONTAINS within a subroutine, although mentions using it in a module. Its example of CONTAINS within a MODULE (http://www.personal.psu.edu/jhm/f90/examples/modproc.f) doesn't even use IMPLICIT NONE, which I believe is very dodgy.
I am still concerned that when I implemented two "correct" ways of handling these strings (possibly implemented incorrectly), but neither raised so much as a warning - let alone a compiler error - in spite of corrupting the memory at runtime. I have all the warnings on, including the Check Routine Interfaces. I also still not clear what is wrong with the original function definition CHARACTER*(*) - which at least ran correctly.
I'm sorry if this comes across as a bit of a whine. I've been doing Fortran on and off for a long time - and quite a lot in the last 4 years - and yet somehow I don't feel I understand it any better than I did 20 years ago. I have a colleague who's done almost exclusively Fortran for 40 years, and he admits that he just keeps trying things until they work...
No, that is not correct in that if the function is a "contained procedure" you don't repeat the declaration as the contained procedure makes the interface. Also you need some commas and colons...
I suggest getting a book on modern Fortran - there's a lot that's new in the last 25 years.
There is an excellent book - Guide to Fortran 2003 Programming - Walter S Bairnard -- from Springer -- it is pretty good to learn the new stuff.
mecej4 is really good at this stuff - along with all the other programmers, MAGNI -- it is a program that mecej4 basically sorted out for me and it shows how to do a lot of stuff - you are interested in - download it and look at the code. -- The program does water supply analysis.
Finally - read this forum everyday - you see a lot of questions and the best answers.
Finally - everyone is learning all the time - we all just a different places on the journey.
And have fun.