- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My Fortran-C mixed language dll compiles and links without any errors. I have a Fortran executable that calls functions in this dll and during execution when it comes to the second PRINT statement in the code below, I get the following error:
Unhandled exception at 0x00404e05 in Driver.exe: 0xC0000005: Access violation writing location 0xa4858d14.
Here is the relevant code from the executable:
PROGRAM DRIVER
IB = 1
CALL RGKNPATCH( IB, NPATCH)
PRINT *, " NPATCH = ", NPATCH
CALL RGKNPAN( IB, NPANC, NPAND, NPANP)
PRINT *, " NPANC = ",NPANC, "NPAND = ",NPAND, "NPANP = ",NPANP
.
.
.
In one Fortran source file from the dll, I have:
!============================================================
subroutine RGKNPATCH ( ib, npatch)
! Expose subroutine RGKNPATCH to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::RGKNPATCH
USE CPROC
! Variables
INTEGER(4), INTENT(IN) :: ib
INTEGER(4), INTENT(OUT) :: npatch
! Body of RGKNPATCH
CALL RGKNPATCHX( ib, npatch)
end subroutine RGKNPATCH
!============================================================
subroutine RGKNPAN ( ib, npanc, npand, npanp)
! Expose subroutine RGKNPAN to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::RGKNPAN
USE CPROC
! Variables
INTEGER(4), INTENT(IN) :: ib
INTEGER(4), INTENT(OUT) :: npanc
INTEGER(4), INTENT(OUT) :: npand
INTEGER(4), INTENT(OUT) :: npanp
! Body of RGKNPAN
CALL RGKNPANX( ib, npanc, npand, npanp)
end subroutine RGKNPAN
!============================================================
In a second Fortran source file from the dll, I have:
MODULE CPROC
INTERFACE
SUBROUTINE RGKNPATCHX ( ib, npatch)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cRGKnpatch' :: RGKNPATCHX
!DEC$ ATTRIBUTES VALUE :: ib
!DEC$ ATTRIBUTES REFERENCE :: npatch
INTEGER(4) ib
INTEGER(4) npatch
END SUBROUTINE
SUBROUTINE RGKNPANX ( ib, npanc, npand, npanp)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cRGKnpan' :: RGKNPANX
!DEC$ ATTRIBUTES VALUE :: ib
!DEC$ ATTRIBUTES REFERENCE :: npanc
!DEC$ ATTRIBUTES REFERENCE :: npand
!DEC$ ATTRIBUTES REFERENCE :: npanp
INTEGER(4) ib
INTEGER(4) npanc
INTEGER(4) npand
INTEGER(4) npanp
END SUBROUTINE
END INTERFACE
END MODULE
And in the c source file, I have:
/*-------------------------------------------------------------------*/
void cRGKnpatch( int ib, int* npatch)
{
int np = -1;
if( 1 <= ib && ib <= nbody
&& Bodies[ib] && Bodies[ib]->pPaneMaps)
{
np = Bodies[ib]->pPaneMaps->npanes;
}
*npatch = np;
}
/*-------------------------------------------------------------------*/
void cRGKnpan( int ib, int* npanc, int* npand, int* npanp)
{
int npc = -1;
int npd = -1;
int npp = -1;
if( 0 <= ib && ib <= nbody
&& Bodies[ib] && (Bodies[ib]->qualify & 1))
{
npc = Bodies[ib]->npan[0];
npd = Bodies[ib]->npan[1];
npp = Bodies[ib]->npan[2];
}
*npanc = npc;
*npand = npd;
*npanp = npp;
}
/*-------------------------------------------------------------------*/
These all worked without any problems several years ago when cRGKnpan had just one less argument and it was likely compiled using an old Compaq Visual Fortran. What seems odd to me is that the call to RGKNPATCH and the following PRINT statement are executed without any problem.
I have stepped through the whole execution of the call to RGKNPAN using the debugger and npanc, npand and npanp return with the correct values. Yet as soon as it tries to execute that second PRINT statement, I get the error mentioned above.
Unhandled exception at 0x00404e05 in Driver.exe: 0xC0000005: Access violation writing location 0xa4858d14.
Here is the relevant code from the executable:
PROGRAM DRIVER
IB = 1
CALL RGKNPATCH( IB, NPATCH)
PRINT *, " NPATCH = ", NPATCH
CALL RGKNPAN( IB, NPANC, NPAND, NPANP)
PRINT *, " NPANC = ",NPANC, "NPAND = ",NPAND, "NPANP = ",NPANP
.
.
.
In one Fortran source file from the dll, I have:
!============================================================
subroutine RGKNPATCH ( ib, npatch)
! Expose subroutine RGKNPATCH to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::RGKNPATCH
USE CPROC
! Variables
INTEGER(4), INTENT(IN) :: ib
INTEGER(4), INTENT(OUT) :: npatch
! Body of RGKNPATCH
CALL RGKNPATCHX( ib, npatch)
end subroutine RGKNPATCH
!============================================================
subroutine RGKNPAN ( ib, npanc, npand, npanp)
! Expose subroutine RGKNPAN to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::RGKNPAN
USE CPROC
! Variables
INTEGER(4), INTENT(IN) :: ib
INTEGER(4), INTENT(OUT) :: npanc
INTEGER(4), INTENT(OUT) :: npand
INTEGER(4), INTENT(OUT) :: npanp
! Body of RGKNPAN
CALL RGKNPANX( ib, npanc, npand, npanp)
end subroutine RGKNPAN
!============================================================
In a second Fortran source file from the dll, I have:
MODULE CPROC
INTERFACE
SUBROUTINE RGKNPATCHX ( ib, npatch)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cRGKnpatch' :: RGKNPATCHX
!DEC$ ATTRIBUTES VALUE :: ib
!DEC$ ATTRIBUTES REFERENCE :: npatch
INTEGER(4) ib
INTEGER(4) npatch
END SUBROUTINE
SUBROUTINE RGKNPANX ( ib, npanc, npand, npanp)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cRGKnpan' :: RGKNPANX
!DEC$ ATTRIBUTES VALUE :: ib
!DEC$ ATTRIBUTES REFERENCE :: npanc
!DEC$ ATTRIBUTES REFERENCE :: npand
!DEC$ ATTRIBUTES REFERENCE :: npanp
INTEGER(4) ib
INTEGER(4) npanc
INTEGER(4) npand
INTEGER(4) npanp
END SUBROUTINE
END INTERFACE
END MODULE
And in the c source file, I have:
/*-------------------------------------------------------------------*/
void cRGKnpatch( int ib, int* npatch)
{
int np = -1;
if( 1 <= ib && ib <= nbody
&& Bodies[ib] && Bodies[ib]->pPaneMaps)
{
np = Bodies[ib]->pPaneMaps->npanes;
}
*npatch = np;
}
/*-------------------------------------------------------------------*/
void cRGKnpan( int ib, int* npanc, int* npand, int* npanp)
{
int npc = -1;
int npd = -1;
int npp = -1;
if( 0 <= ib && ib <= nbody
&& Bodies[ib] && (Bodies[ib]->qualify & 1))
{
npc = Bodies[ib]->npan[0];
npd = Bodies[ib]->npan[1];
npp = Bodies[ib]->npan[2];
}
*npanc = npc;
*npand = npd;
*npanp = npp;
}
/*-------------------------------------------------------------------*/
These all worked without any problems several years ago when cRGKnpan had just one less argument and it was likely compiled using an old Compaq Visual Fortran. What seems odd to me is that the call to RGKNPATCH and the following PRINT statement are executed without any problem.
I have stepped through the whole execution of the call to RGKNPAN using the debugger and npanc, npand and npanp return with the correct values. Yet as soon as it tries to execute that second PRINT statement, I get the error mentioned above.
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting Edward Stanley
Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c
You have /iface:cvf on the DLL but not on the main program. When compiling the main program how does the compiler know that the Fortran entry points in the DLL are not using the ifort default calling convention? Are the Fortran DLL routines in a module? If not, do you have an interface block for the routines that has all the !DEC$ ATTRIBUTES stuff required for the CVF calling convention? If neither, then there's your problem.
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ramblings only...
- Exploding print statements make it sound like stack corruption.
- What ifort version? Which C compiler, what C compiler version? What command line options for both?
- Some of the the lines with compiler directives are getting pretty long. 12.1 docs say you can't go past column 72 even in free form (which might be an error in the docs - but it doesn't take much to get a directive treated as a comment and ignored). No warnings or other informational messages in the build log?
- What's the declaration (and perhaps initialisation and/or subsequent memory allocation) for Bodies? Is it indexable from zero through to and including nbody (in the context of an array(N) in C being indexed from zero through to N-1)? ib has a "valid" lower index of one in cRGKnpath, but zero in cRGKnpan, is that intentional?
- Perhaps they've been elided, butI don't see any implicit none statements inside the program units or interface bodies. Are the variables in the actual argument lists for the subroutine calls in the main program all INTEGER(4)? Are the subroutines external or in a module?
- Are you familiar with the C interoperability stuff from F2003? Because it is standard it lets you test this sort of stuff on different processors, which can help isolate bugs. I find its syntax much cleaner and more robust to mistakes that the !DEC$ business too.
- What you've presented is not far off being a compilable test case. Is it possible to provide or write a little bit more code to make something that can be examined in isolation? Will help cut down the signal to rambling ratio too...
- Exploding print statements make it sound like stack corruption.
- What ifort version? Which C compiler, what C compiler version? What command line options for both?
- Some of the the lines with compiler directives are getting pretty long. 12.1 docs say you can't go past column 72 even in free form (which might be an error in the docs - but it doesn't take much to get a directive treated as a comment and ignored). No warnings or other informational messages in the build log?
- What's the declaration (and perhaps initialisation and/or subsequent memory allocation) for Bodies? Is it indexable from zero through to and including nbody (in the context of an array(N) in C being indexed from zero through to N-1)? ib has a "valid" lower index of one in cRGKnpath, but zero in cRGKnpan, is that intentional?
- Perhaps they've been elided, butI don't see any implicit none statements inside the program units or interface bodies. Are the variables in the actual argument lists for the subroutine calls in the main program all INTEGER(4)? Are the subroutines external or in a module?
- Are you familiar with the C interoperability stuff from F2003? Because it is standard it lets you test this sort of stuff on different processors, which can help isolate bugs. I find its syntax much cleaner and more robust to mistakes that the !DEC$ business too.
- What you've presented is not far off being a compilable test case. Is it possible to provide or write a little bit more code to make something that can be examined in isolation? Will help cut down the signal to rambling ratio too...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The debugger should be of assistance here. However, I would suggest using MessageBox inside the C-code to display exactly what the C-functions are sending and MessageBox inside the Fortran subroutines to display exactly what they think they are receiving and going on from there. It is possible to get a confusion between sending an address (pointer) which goes on the stack as a value which should be recovered as a value but the Fortran might recover it as an address to an address, or possibly vise versa!
Also, make sure that the calling conventions match between the C-code and the Fortran code calling it or else the stack is likely top get corrupted and that may eventually cause what you are seeing. Remember that IVF uses a default calling convention that is different from that of CVF.
Also, make sure that the calling conventions match between the C-code and the Fortran code calling it or else the stack is likely top get corrupted and that may eventually cause what you are seeing. Remember that IVF uses a default calling convention that is different from that of CVF.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is this a C source file or CPP source file?
If CPP then you may need to declare your CPP functions as
extern "C" void cRGKnpatch( int ib, int* npatch);
extern "C" void cRGKnpan( int ib, int* npanc, int* npand, int* npanp);
Also, your code will have portability issues.
On your Fortran side, consider using
INTEGER(C_INT) ib
INTEGER(C_PTR) npanc
...
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- What ifort version? Which C compiler, what C compiler version? What command line options for both?
ifort version = 12.1.3514
C compiler = VS2005 version 2.0.50727 SP2
Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for c portion of dll:
/Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /Gm /EHsc /RTC1 /MTd /Fp".\Debug/RG2W.pch" /Fo".\Debug/" /Fd".\Debug/" /FR".\Debug\" /W3 /nologo /c /Zi /TC /errorReport:prompt
- Some of the the lines with compiler directives are getting pretty long. 12.1 docs say you can't go past column 72 even in free form (which might be an error in the docs - but it doesn't take much to get a directive treated as a comment and ignored). No warnings or other informational messages in the build log?
I don't get any warnings concerning line length.
- What's the declaration (and perhaps initialisation and/or subsequent memory allocation) for Bodies? Is it indexable from zero through to and including nbody (in the context of an array(N) in C being indexed from zero through to N-1)? ib has a "valid" lower index of one in cRGKnpath, but zero in cRGKnpan, is that intentional?
The zero in cRGKnpan was an oversight. Bodies is really immaterial to the problem. I can assign different values to npanc, npand and npanp directly and comment out that block of code referencing Bodies and still get the error.
- Perhaps they've been elided, butI don't see any implicit none statements inside the program units or interface bodies. Are the variables in the actual argument lists for the subroutine calls in the main program all INTEGER(4)? Are the subroutines external or in a module?
There are no IMPLICIT NONE statements anywhere. The variables are indeed INTEGER(4)'s.
- Are you familiar with the C interoperability stuff from F2003? Because it is standard it lets you test this sort of stuff on different processors, which can help isolate bugs. I find its syntax much cleaner and more robust to mistakes that the !DEC$ business too.
No, I am not familiar with this. I haven't done any significant Fortran coding in over twenty years.
- What you've presented is not far off being a compilable test case. Is it possible to provide or write a little bit more code to make something that can be examined in isolation? Will help cut down the signal to rambling ratio too...
I might try to do this if I can find the time.
ifort version = 12.1.3514
C compiler = VS2005 version 2.0.50727 SP2
Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for c portion of dll:
/Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /Gm /EHsc /RTC1 /MTd /Fp".\Debug/RG2W.pch" /Fo".\Debug/" /Fd".\Debug/" /FR".\Debug\" /W3 /nologo /c /Zi /TC /errorReport:prompt
- Some of the the lines with compiler directives are getting pretty long. 12.1 docs say you can't go past column 72 even in free form (which might be an error in the docs - but it doesn't take much to get a directive treated as a comment and ignored). No warnings or other informational messages in the build log?
I don't get any warnings concerning line length.
- What's the declaration (and perhaps initialisation and/or subsequent memory allocation) for Bodies? Is it indexable from zero through to and including nbody (in the context of an array(N) in C being indexed from zero through to N-1)? ib has a "valid" lower index of one in cRGKnpath, but zero in cRGKnpan, is that intentional?
The zero in cRGKnpan was an oversight. Bodies is really immaterial to the problem. I can assign different values to npanc, npand and npanp directly and comment out that block of code referencing Bodies and still get the error.
- Perhaps they've been elided, butI don't see any implicit none statements inside the program units or interface bodies. Are the variables in the actual argument lists for the subroutine calls in the main program all INTEGER(4)? Are the subroutines external or in a module?
There are no IMPLICIT NONE statements anywhere. The variables are indeed INTEGER(4)'s.
- Are you familiar with the C interoperability stuff from F2003? Because it is standard it lets you test this sort of stuff on different processors, which can help isolate bugs. I find its syntax much cleaner and more robust to mistakes that the !DEC$ business too.
No, I am not familiar with this. I haven't done any significant Fortran coding in over twenty years.
- What you've presented is not far off being a compilable test case. Is it possible to provide or write a little bit more code to make something that can be examined in isolation? Will help cut down the signal to rambling ratio too...
I might try to do this if I can find the time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is this a C source file or CPP source file?
It's a c source file.
On your Fortran side, consider using
INTEGER(C_INT) ib
INTEGER(C_PTR) npanc
...
Thanks, I'll look into this.
It's a c source file.
On your Fortran side, consider using
INTEGER(C_INT) ib
INTEGER(C_PTR) npanc
...
Thanks, I'll look into this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting Edward Stanley
Command line options for Fortran calling app:
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c
/nologo /debug:full /Od /warn:interfaces /module:"Debug\" /object:"Debug\" /traceback /check:bounds /libs:static /threads /dbglibs /c
Command line options for Fortran portion of dll:
/nologo /debug:full /Od /Qsave /iface:cvf /module:"Debug/" /object:"Debug/" /traceback /check:bounds /libs:static /threads /dbglibs /c
You have /iface:cvf on the DLL but not on the main program. When compiling the main program how does the compiler know that the Fortran entry points in the DLL are not using the ifort default calling convention? Are the Fortran DLL routines in a module? If not, do you have an interface block for the routines that has all the !DEC$ ATTRIBUTES stuff required for the CVF calling convention? If neither, then there's your problem.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the help Ian! Everything worked fine after adding the /iface:cvf option to the main program.
![](/skins/images/3344F5B3B76C91485ED0E980FD0CA95E/responsive_peak/images/icon_anonymous_message.png)
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page