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

Fortran 2003 C-interoperable code: possible wrong assembly generation by the compiler

riccardo42
Beginner
827 Views
Hi,

I'm exploring the opportunities offered by the Fortran 2003 standard to create C-interoperable functions and subroutines and I stumbled in what seems like an error in the code generated by the compiler on a rather simple function.

Here is the fortran module (lines marked as OPTIONAL can be commented without changing the behaviour of the code generated, I left them to give an idea of what my original test was):


----------- test_module.f90 -----------
module test_module

contains

function arrayfunc(size) bind(c)
use iso_c_binding
implicit none
integer(c_int),value::size
type(c_ptr),target::arrayfunc
real(c_double),target,allocatable,dimension(:)::array
integer::i !OPTIONAL

print *,"The size received is: ",size

allocate(array(1:size)) ! OPTIONAL
if (.not. allocated(array)) then ! OPTIONAL
print *, "Array not allocated..." ! OPTIONAL
end if ! OPTIONAL
! OPTIONAL
do i=1,size ! OPTIONAL
array(i) = i*i ! OPTIONAL
enddo ! OPTIONAL
! OPTIONAL
arrayfunc=C_LOC(array) ! OPTIONAL
return
end function arrayfunc

end module test_module
----------------------------

Here is the C header file:

----------- test_module.h -----------
#ifndef TEST__MODULE_H
#define TEST__MODULE_H

// Intent: interface Fortran with C to create a function that returns
// a C array of allocated memory
extern double *arrayfunc(int size);

#endif
----------------------------------------

And this is the C code used to call the fortran function:

------------- test.c -----------------

#include
#include
#include "test_module.h"

int main(int argc, char *argv[])
{
double *testarray=NULL;
int i;

testarray=arrayfunc(10);

for(i=0;i<10;i++)
printf("Element %2d of the Fortran array: %g\n", i, testarray);

return 0;
}
---------------------------

The function arrayfunc (which should have allocated an array and passed it to the C function) is supposed to print it's "size" argument as the first action (10, which is to be received by value, as explicitly specified in the declaration), however both on ifort 10.1 (ia32) and ifort Version 11.1 (ia64) where I tested the code, the argument seems to be received incorrectly (in fact in the 64bit example, the variable seems to point to uninitialized memory...).

This is what happens with ifort 10.1 on my atom N270 (ia32):

$ ./test
The size received is: 134520820

and those are a couple of results on my Q9550 (ia64 with a 64bit ubuntu):

$ ./test 
The size received is: -1720334552
Segmentation fault
$ ./test
The size received is: -2028769016
Segmentation fault
$ ./test
The size received is: 1024856360
forrtl: severe (41): insufficient virtual memory
Image PC Routine Line Source
libintlc.so.5 00007F6133E3BB2D Unknown Unknown Unknown
libintlc.so.5 00007F6133E3A635 Unknown Unknown Unknown
libifcore.so.5 00007F6134842535 Unknown Unknown Unknown
libifcore.so.5 00007F61347B4A2D Unknown Unknown Unknown
libifcore.so.5 00007F6134801CF8 Unknown Unknown Unknown
libifcore.so.5 00007F6134801B51 Unknown Unknown Unknown
libtest_module.so 00007F6134D4198B Unknown Unknown Unknown
test 000000000040068D Unknown Unknown Unknown
libc.so.6 00007F61349ED5A6 Unknown Unknown Unknown
test 00000000004005A9 Unknown Unknown Unknown

I have tested the same example with 2 other compilers on both computers and the result was, as expected, something like:

 The size received is:           10
Element 0 of the Fortran array: 1
Element 1 of the Fortran array: 4
Element 2 of the Fortran array: 9
Element 3 of the Fortran array: 16
Element 4 of the Fortran array: 25
Element 5 of the Fortran array: 36
Element 6 of the Fortran array: 49
Element 7 of the Fortran array: 64
Element 8 of the Fortran array: 81
Element 9 of the Fortran array: 100

The code was interfaced with gcc-4.33 (although for what I know about assembly I'm rather positive it isn't relevant to the matter at hand) and the fortran code compiled in many different ways (as a shared library, as a simple object file, with/without debugging symbols, with/without optimization enabled and so forth...).

Now because I'm not coding in Fortran since a long while the fortran code might not be fit to my purpose, however I think there is still a glitch in the compiler that might be worth a bug report.

I read some documentation on this site and elsewhere about C-Fortran interfaces, but since I'm new to the task, any comment, suggestion or costructive critic will be highly appreciated.

Thank you for your time and patience,

Riccardo

PS: I apologize for the poor look of this post (I'm in the software network since half an hour and I'm not yet skilled with the composer :-) )

0 Kudos
1 Solution
Steven_L_Intel1
Employee
827 Views
Curiously, this fails on Linux but works on Windows. I can't quite tell what the Linux code is doing except that it doesn't seem to be doing the "obvious" error of ignoring VALUE. Rather, it seems to be looking in the wrong location for the argument.

I have escalated this to the developers - the issue ID is DPD200137800. As a workaround, I'd suggest removing the VALUE attribute and passing the size by reference.

View solution in original post

0 Kudos
8 Replies
riccardo42
Beginner
827 Views
So far I've tested this on IA-32 with 11.1 and it works correctly. I'll try some other combinations.

is there any information i can add to help track down the problem (e.g. i could post the annotated assembly, if it could be of any help, or some other info about my system)?

Thank you very much for your help!

Riccardo
0 Kudos
Steven_L_Intel1
Employee
827 Views
I retract what I wrote earlier (I deleted my post before seeing yours). The test I did was not close enough to what you did. I can see a problem on IA-32 but don't yet know where the problem lies. I'll get back to you.
0 Kudos
TimP
Honored Contributor III
827 Views
In order to reproduce the error, I used
ifort -c -g test_module.f90
icc -g test.c test_module.o -lifcore
The result varies according to whether I run in idb or directly from command line, and with optimization.
As indicated, 'gfortran test_module.f90 test.c' produces the expected results.
0 Kudos
Steven_L_Intel1
Employee
828 Views
Curiously, this fails on Linux but works on Windows. I can't quite tell what the Linux code is doing except that it doesn't seem to be doing the "obvious" error of ignoring VALUE. Rather, it seems to be looking in the wrong location for the argument.

I have escalated this to the developers - the issue ID is DPD200137800. As a workaround, I'd suggest removing the VALUE attribute and passing the size by reference.
0 Kudos
Steven_L_Intel1
Employee
827 Views
I forgot to mention - there's an error in your code as well. You need to declare the allocatable array with the SAVE attribute, as without it, the array is automatically deallocated on exit from the routine.
0 Kudos
riccardo42
Beginner
827 Views
Curiously, this fails on Linux but works on Windows. I can't quite tell what the Linux code is doing except that it doesn't seem to be doing the "obvious" error of ignoring VALUE. Rather, it seems to be looking in the wrong location for the argument.

I have escalated this to the developers - the issue ID is DPD200137800. As a workaround, I'd suggest removing the VALUE attribute and passing the size by reference.


My personal solution was to just use a subroutine with an extra argument for the output, but I'll try the size passed by reference as well, Thank you!

I had the impression that something funny was happening on the stack, but not being so good with asm, I tought not to mention it.

Thank you for your help,
Riccardo

PS: you definitely made my day with the SAVE correction. As a C programmer I had never expected garbage collecting behaviours from an "old" language like fortran. That's explains all those: "double free errors" from libc :-D
0 Kudos
Steven_L_Intel1
Employee
827 Views
Your workaround is good - the problem is that on Linux and Mac OS, the compiler is using a hidden extra argument to return values that are small structures, such as C_PTR - it doesn't do this on Windows. Since C isn't calling the routine this way, the arguments are in the wrong place and everything goes downhill from there.

This will be fixed in a future update. The compiler ought not to be using hidden arguments for any BIND(C) routine.
0 Kudos
Steven_L_Intel1
Employee
827 Views
This is fixed in 11.1 Update 3.
0 Kudos
Reply