Wrong variable length

Wrong variable length

Hi,

I`m having problems copying "strings" in Fortran:

subroutine setthis(this_, tam)

!DEC$ ATTRIBUTES DLLEXPORT, ALIAS: '_setthis_' ::SETTHIS

CHARACTER*5 this_

CHARACTER*5 this_c

common /this/ this_c

!$omp threadprivate(/this/)

this_c(1:5)=this_(1:5)

end subroutine

And in the last instruction, it crashes with:

forrtl: severe (408): fort: (18): Dummy character variable 'THIS_' has length 5 which is greater then actual variable length -858993460

Instead if this, if I do this_c(1:5)='aa', this works fine!.. Any ideas?

I`m using Intel Visual Fortran Compiler Professional for applications running on IA-32, Version 11.1 Build 20100806 Package ID: w_cprof_p_11.1.067

Thanks in advance!

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Much depends on the contents of the argument this_ at subroutine entry. Therefore, I would have to see the source lines with the CALL to the subroutine, or a debugger view of the variable at entry.

What happens if you make this code serial? What is the type and purpose of the second argument tam ? Why the underscore in a variable name?

That the code works if your change the assignment statement, by putting a character constant on the right side, has little bearing about the problem.

As you need to know, if you are calling the Fortran subroutine from another language, there is an extra hidden length-argument to be passed for each character-type argument. If that extra argument were left out of a subroutine call from C, for example, the Fortran subroutine would pull off whatever was pushed on the stack before tam -- that may very well be the return address, and that would set off the complaint about the negative string length.

This is the call stack before executing the problematic line (removed also the tam variable):

libifcoremdd.dll!0082c387()

[Los marcos siguientes pueden no ser correctos o faltar, no se han cargado smbolos para libifcoremdd.dll]

libifcoremdd.dll!0082c751()

> B.dll!SETTHIS(CHARACTER(5) THIS_='W6 ', .tmp..T4__V$6=) Lnea 11 + 0xce bytes Fortran

a.dll!A::setthis() Lnea 253 + 0x52 bytes C++

All variables seem to be correct at this moment:

THIS_ 'W3 ' CHARACTER(5)

THIS_C ' ' CHARACTER(5)

The call and the declaration in the C++ part:

setthis_((char*)(thiss.substr(0,4).c_str()));

extern "C" void setthis_(char * this_);

As I wrote in #1, you have to be aware of how character arguments are passed to Fortran from C/C++. The declaration

extern "C" void setthis_(char * this_);

does not meet the requirements, which are described in the Mixed Language Programming chapter(s) of the Fortran User Guide. You need an extra integer argument in which you pass the current length of the string this_.

As an alternative, cast aside all that !DEC$ business and use C interoperability from F2003. For this C++ function declaration:

 extern "C" void setthis_(const char * this_);

...a fortran procedure that looks a bit like this...

subroutine setthis(this_) BIND(C, NAME='setthis_')
  USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR
  IMPLICIT NONE
  CHARACTER(KIND=C_CHAR), INTENT(IN) :: this_(5)
  CHARACTER(5) :: this_c
  common /this/ this_c
  !$omp threadprivate(/this/)
  INTEGER :: i
  !****
  FORALL (i=1:5) this_c(i:i) = this_(i)
end subroutine

...may suit and would be portable across a variety of modern compilers. Avoids all that worrying about hidden integer parameters and name decorations.

Note that if thiss is a std::string on the C++ side you can get rid of the cast; and this_c(5:5) is always going to be ACHAR(0) - you might be able to avoid storing it. You can also directly manipulate fortran common variables (and (better) module variables) in a standard way from C(++) too, which would avoid the need for the subroutine in the first place.

Leave a Comment

Please sign in to add a comment. Not a member? Join today