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

Wrong variable length

aurora_s
Beginner
495 Views
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!

0 Kudos
4 Replies
mecej4
Honored Contributor III
494 Views
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.
0 Kudos
aurora_s
Beginner
495 Views
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_);

0 Kudos
mecej4
Honored Contributor III
495 Views
As I wrote in #1, you have to be aware of how character arguments are passed to Fortran from C/C++. The declaration

[cpp]extern "C" void setthis_(char * this_);
[/cpp]

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_.
0 Kudos
IanH
Honored Contributor II
495 Views
As an alternative, cast aside all that !DEC$ business and use C interoperability from F2003. For this C++ function declaration:
[cpp] extern "C" void setthis_(const char * this_);[/cpp]
...a fortran procedure that looks a bit like this...

[fortran]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
[/fortran]

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




0 Kudos
Reply