Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

CHARACTER(LEN=*) functions

Mike_S_4
Beginner
2,179 Views

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?

0 Kudos
12 Replies
andrew_4619
Honored Contributor II
2,180 Views
! 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')

 

0 Kudos
Mike_S_4
Beginner
2,180 Views

Thanks, @andrew_4619.

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.:

CHARACTER*1024 QUOTESTR

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...

0 Kudos
mecej4
Honored Contributor III
2,180 Views

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.

0 Kudos
andrew_4619
Honored Contributor II
2,179 Views

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. 

 

 

0 Kudos
Mike_S_4
Beginner
2,179 Views

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:

    subroutine X

        integer Y

    end subroutine

And in another file or project:

    integer function Y()

    end function

Is this just bad practice, and should all functions (and subroutines?) be defined in modules?

0 Kudos
Steven_L_Intel1
Employee
2,180 Views

Suggested reading: https://software.intel.com/en-us/blogs/2012/01/05/doctor-fortran-gets-explicit-again

0 Kudos
andrew_4619
Honored Contributor II
2,179 Views

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

 

0 Kudos
Steven_L_Intel1
Employee
2,180 Views

I'll take another look - maybe regarding the mention of interface blocks.

0 Kudos
JohnNichols
Valued Contributor III
2,177 Views

I have this beside my bed, read it every night - still lost --

0 Kudos
Mike_S_4
Beginner
2,180 Views

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:

MODULE function_definition

IMPLICIT NONE

CHARACTER ALLOCATABLE(LEN=:) FUNCTION do_something

CONTAINS

FUNCTION do_something()

CHARACTER ALLOCATABLE(LEN=:) do_something

END FUNTION

END MODULE

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...

0 Kudos
Steven_L_Intel1
Employee
2,180 Views

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.

0 Kudos
JohnNichols
Valued Contributor III
2,177 Views

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.

John

0 Kudos
Reply