Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29279 ディスカッション

32-bit App Fails when Built on 64-bit machine

Kipling__Michael
ビギナー
1,171件の閲覧回数

I'm building a 32-bit app on a 64-bit machine. My two colleagues are building the same app on 32-bit machines. Mine fails while theirs are fine.

I created a simple Fortran routine called Junk to illustrate the problem. The program fails when the 4th variable in the Junk call list is used. The error message is "Dummy character variable 'CHAR4' has length which is greater than the actual variable length -858993460". If I reduce the number of variables in the call list to three, I have no problems.

The dialog is written with C++. It callsthe C routine junkc which calls a Fortran routine Junk. The C routines and Fortran routines are built into seperate DLLs.

SUBROUTINE Junk(char1, char2, char3, char4)
!DEC$ ATTRIBUTES DECORATE, ALIAS:'junk' :: Junk
!DEC$ ATTRIBUTES DLLEXPORT::Junk

CHARACTER(LEN=5), INTENT(IN) :: char1
CHARACTER(LEN=5), INTENT(IN) :: char2
CHARACTER(LEN=5), INTENT(IN) :: char3
CHARACTER(LEN=5), INTENT(IN) :: char4

CHARACTER(LEN=5) :: char1a
CHARACTER(LEN=5) :: char2b
CHARACTER(LEN=5) :: char3c
CHARACTER(LEN=5) :: char4d

char1a = ' '
char2a = ' '
char3a = ' '
char4a = ' '

char1a = char1
char2b = char2
char3c = char3
char4d = char4 ! <--- Program fails here

RETURN
END

The C routine which calls the Fortran routine is called junkc. It uses the routine cluCpFstr to convert C strings to Fortran strings.

void junkc(void)
{
char char1[5+1], char2[5+1], char3[5+1], char4[5+1];
char char1a[5], char2a[5], char3a[5], char4a[5];

strcpy(char1,"abcde");
strcpy(char2,"fghij");
strcpy(char3,"klmno");
strcpy(char4,"pqrst");

cluCpFstr(char1, 5+1, char1a, 5);
cluCpFstr(char2, 5+1, char2a, 5);
cluCpFstr(char3, 5+1, char3a, 5);
cluCpFstr(char4, 5+1, char4a, 5);

junk(char1a, char2a, char3a, char4a);
}

void cluCpFstr(char *src_str,int src_size,char *target_str,int target_size)
{
int i,cplen;

for(i=0;i target_str = ' ';
cplen = (src_size > target_size) ? target_size : src_size;
for(i=0;i target_str = src_str;
}

I've tried using all of the compiler diagnostics, but have not been able to solve this problem.

Mike

0 件の賞賛
1 解決策
Steven_L_Intel1
従業員
1,171件の閲覧回数
I think it's just coincidence/luck that the others "work". The Fortran code is expecting string lengths to be passed but the C++ code isn't passing them. The code then looks to uninitialized storage for the length. It may seem to work if you don't have string bounds checking enabled. To fix this, add:

!DEC$ ATTRIBUTES REFERENCE :: char1,char2,char3,char4

to the Fortran routine. This will tell Fortran not to expect lengths.

元の投稿で解決策を見る

6 返答(返信)
Steven_L_Intel1
従業員
1,172件の閲覧回数
I think it's just coincidence/luck that the others "work". The Fortran code is expecting string lengths to be passed but the C++ code isn't passing them. The code then looks to uninitialized storage for the length. It may seem to work if you don't have string bounds checking enabled. To fix this, add:

!DEC$ ATTRIBUTES REFERENCE :: char1,char2,char3,char4

to the Fortran routine. This will tell Fortran not to expect lengths.
Kipling__Michael
ビギナー
1,171件の閲覧回数
Steve,

You are right on the money again.

I use the !DEC$ ATTRIBUTES REFERENCE in all of the interfaces I've created for C routines called by Fortran which pass character variables, but I had not used it in Fortran routines called by C.

What I don't understand is why this was all working fine until I compiled on my new 64-bit machine. We probably have a couple of hundred calls to Fortran from C, and a lot of this code has been around for a couple of decades.

Anyway, thank's again.

Mike
Steven_L_Intel1
従業員
1,171件の閲覧回数
It could be a combination of things. If you're not using bounds checking, this might not be a problem. Going from an older (say, 11.0 or earlier) version to a current one might also bring this added check to the passed length.

I suggest you also start looking at the Fortran 2003 C interoperability features, though one area they are weak in is exactly what you are doing here - calling Fortran with character strings. For an "interoperable" routine, you'd have to declare the character arguments as an array of single characters. You'd then have to TRANSFER those to a character(n) variable to do anything with them. But with BIND(C), you could do away with all the directives save DLLEXPORT.
Kipling__Michael
ビギナー
1,171件の閲覧回数
Steve,

I have modified 190 Fortran routines called by C to use!DEC$ ATTRIBUTES REFERENCE.It required that Iduplicate 50 of them that arealso called by other Fortran routines so that the character string length was passed.

This should have solved my problem. However, early on in tracking down the problem, I had turned on the Floating Point option toCheck Floating-Point Stack - Yes (/Qfp-stack-check). This had uncovered a couple of errors which I had corrected, and I left it set to Yes.

When I tried to run after correcting everything, I was receiving the runtime error "Unhandled exception at 0x11466286 (CLASH_FsrcD.dll) in CLASH.exe: 0xC0000005: Access violation writing location 0x00000000". The error occured when a local character variable was intialized the second time the routine was called. Setting the Check Floating-Point Stack - No eliminated the error and the program runs correctly.

Mike
anthonyrichards
新規コントリビューター III
1,171件の閲覧回数
Shouldn't the C- function 'junk' prototype be declared

extern "C" { void __stdcall junk(char *char1, char *char2, char *char3, char *char4); }

or

extern "C" { void __cdecl junk(char *char1, char *char2, char *char3, char *char4); }

?
Kipling__Michael
ビギナー
1,171件の閲覧回数
The C and Fortran routines are stored in separate DLL's which can be accessed by the C++ routines. If we call a Fortran from C++, then we would add the following to the C++ header file.

extern "C" {__declspec(dllimport) void junk(char1[5], char2[5], char3[5], char4[5]);}

The actual call from C++ would be written like this, the same as from C:

junk(char1, char2, char3, chaqr4);

We have not needed to add a prototype for the Fortran routines called from C.
返信