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

Run-time error from library routine

dajum
Novice
815 Views
this code fragment

DO I=1,100000

write(line,*)' daj i= ',i

write(*,*)line

iret = cwrstat(line)

DO j=1,100000

a=a+1.0 + i/1000.0

enddo

if( i.eq.1 .or. i.eq.100)write(*,*)' daj ',a

enddo

Generates this error:
forrtl: severe (8): internal consistency check failure, file for_desc_item.c, line 590

CWRSTAT is in a DLL.

Any help as to what causes this?



0 Kudos
7 Replies
Steven_L_Intel1
Employee
815 Views
Insufficient information. The error is equivalent to an internal compiler error, but it is most often caused by the program "stomping on memory" somewhere. One can't analyze this based on a code fragment.
0 Kudos
dajum
Novice
815 Views
I'm using 11.1.065 on a 32 bit machine. The dll is made for 32 bits. You should probably take out the pause statement too.
0 Kudos
Steven_L_Intel1
Employee
815 Views
Even though there are dependent DLLs missing, I can see the problem. The DLL routines are evidently built with the STDCALL interface, which is why their names end in @4, @8, etc. You declare interfaces to these routines with blocks such as this:

[fortran]!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES DLLIMPORT,ALIAS:'_cwrstat@8' :: CWRSTAT
!DEC$ ELSE
!DEC$ ATTRIBUTES DLLIMPORT,ALIAS:'cwrstat' :: CWRSTAT
!DEC$ ENDIF[/fortran]
Note that you use ALIAS to explicitly add the @8 to the name, but you don't also specify STDCALL. A big hint - if you ever think you need to add the @n to an ALIAS, you're almost certainly making a mistake. It would have been ok if you compiled your source with /iface:cvf or /iface:stdref, but you didn't. The result is that every time you call CWRSTAT, you corrupt the stack by 8 bytes since the called routine pops 8 bytes from the stack as does the caller.

What I suggest you use instead is simply:

!DEC$ ATTRIBUTES STDCALL, REFERENCE, DLLIMPORT :: CWRSTAT

with similar declarations of the other routines. The compiler will automatically add the appropriate "decoration" and will know that the called routine pops the stack.

What I find a bit puzzling is that some of the DLL routines do not have the @n suffix, though you're not calling those. It's unusual to have a mix in the same DLL. You should read this DLL's documentation carefully to make sure that you are using the right calling and argument passing conventions.
0 Kudos
dajum
Novice
815 Views
It isn't that straightforward. The function is defined with

extern "C" {
__declspec(dllexport) int __stdcall cwrstat( char *message, int len);
}

Which I think explains the name mangling and why the existing code links and runs. But I'm not sure it explains the memory overwrite.

The suggested changes to the declarations didn't work.
0 Kudos
Steven_L_Intel1
Employee
815 Views
The function being declared that way supports my comment that you're using the wrong calling convention. The C routine wants STDCALL (that's what the __stdcall does) and therefore the caller has to know to use STDCALL conventions. Intel Fortran uses the C convention by default, so you have to use ATTRIBUTES STDCALL to tell it otherwise. This will cause the name to be downcased and the proper "decoration" added.

It may be that the stack corruption was not the issue, but it would surely bite you eventually.

The DLL has at least one other non-standard DLL it depends on that you didn't include, so I can't try it myself.
0 Kudos
Steven_L_Intel1
Employee
815 Views
I also need lsapiw32.dll. Please also attach your corrected Fortran source so I can be sure you made the appropriate changes.
0 Kudos
dajum
Novice
815 Views

Ah ha! The key was to add the interface statement and not just change the attributes line. I hadn't tried that , but now see why it is needed. Thanks. Funny thing is that this DLL has been being used for about 12 years with the same 2 errors in it. But they seem to have canceled out and it has worked fine for all that time. Thanks for helping to fix this.

0 Kudos
Reply