Forum Jump

Select Group :
Select Forum :
Sorted By :
Sort Order :
From The :
 
Thread Tools  Search this thread 
riccardo42
Total Points:
55
Status Points:
5
Green Belt
July 7, 2009 6:31 AM PDT
Fortran 2003 C-interoperable code: possible wrong assembly generation by the compiler
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 <stdlib.h>
#include <stdio.h>
#include "test_module.h"

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

testarray=arrayfunc(10);

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

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 :-) )

riccardo42
Total Points:
55
Status Points:
5
Green Belt
July 7, 2009 8:47 AM PDT
Rate
 
#2
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


Steve Lionel (Intel)
Total Points:
112,121
Status Points:
112,121
Black Belt
July 7, 2009 8:56 AM PDT
Rate
 
#3 Reply to #2
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.



tim18
Total Points:
66,397
Status Points:
66,397
Black Belt
July 7, 2009 10:10 AM PDT
Rate
 
#4 Reply to #3
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.


Steve Lionel (Intel)
Total Points:
112,121
Status Points:
112,121
Black Belt
July 10, 2009 8:47 AM PDT
Rate
 
|Best Answer
#5
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.



Steve Lionel (Intel)
Total Points:
112,121
Status Points:
112,121
Black Belt
July 10, 2009 9:48 AM PDT
Rate
 
#6
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.



riccardo42
Total Points:
55
Status Points:
5
Green Belt
July 10, 2009 11:06 AM PDT
Rate
 
#7 Reply to #5
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


Steve Lionel (Intel)
Total Points:
112,121
Status Points:
112,121
Black Belt
July 22, 2009 12:54 PM PDT
Rate
 
#8 Reply to #7
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.



Steve Lionel (Intel)
Total Points:
112,121
Status Points:
112,121
Black Belt
November 3, 2009 8:52 AM PST
Rate
 
#9 Reply to #8


Intel Software Network Forums Statistics

8285 users have contributed to 31229 threads and 99106 posts to date.
In the past 24 hours, we have 16 new thread(s) 55 new posts(s), and 81 new user(s).

In the past 3 days, the most popular thread for everyone has been comparison cilk++, openmp, pthreads first results The most posts were made to comparison cilk++, openmp, pthreads first results The post with the most views is Very amusing...  Escalated as

Please welcome our newest member tvinni