Bug with ISO_C_BINDING on Mac OS?

Janus Weil janus@gcc.gnu.org
Sat Jun 1 12:14:00 GMT 2013


>> attached are two small test cases (Fortran & C), which try to open a
>> bz2 file for reading (they require a, possibly empty, file 'test.bz2'
>> in the same dir). The Fortran version uses ISO_C_BINDING interfaces
>> for the calls to 'fopen' and 'BZ2_bzReadOpen', and both work as
>> expected on Linux (x86_64):
>
> Yes, there is a bug with ISO_C_BINDING - but the bug is in your code ;-)

Certainly possible. I admit that it took me quite a while to figure
out a working interface on Linux.


> At least the problem below is likely to cause problems on x86-64. I don't
> know why you only see the problem on MacOS, it should also exist on 64bit
> Linux.

Well, I also tried running the test program with valgrind on Linux -
but it did not show any errors there. Also these interfaces have
proven to work with four different compilers: ifort, gfortran, g95,
sunf95.


> You declare:
>
>>    interface
>>      function fOpen (path,mode) bind (c,NAME='fopen')
>>        use, intrinsic :: ISO_C_BINDING
>>        character(c_char) path(*),mode(*)
>>        integer(c_int) :: fOpen
>>      end function
>>    end interface
>
> However, POSIX defines that fopen returns a "FILE *". On most 32 bit
> systems, it should work. However, on a 64bit system, it wont (or only by
> chance). Either you should use a proper pointer like TYPE(c_ptr). Or, if you
> want to use an integer, use: INTEGER(c_intptr_t).

Well, ok, let's try it with TYPE(c_ptr) ...


>>     interface
>>      function bzReadOpen (bzerror,f,verbosity,small,unused,nUnused) bind
>> (c,NAME='BZ2_bzReadOpen')
>>        use, intrinsic :: ISO_C_BINDING
>>        integer(c_int),value :: f,verbosity,small,nUnused
>>        integer(c_int) :: bzReadOpen,bzerror
>>        type(c_ptr) :: unused
>>      end function
>>    end interface
>
> This one looks bogus as well. bzerror and f are both pointers (int * and
> FILE *).
>
> For bzerror: I think you really should use "INTEGER(c_int)"  (w/o VALUE) -
> that way you get a proper error return.

This I'm doing already!


> And for FILE *f: Here, you have to ensure that you pass all 64bits of the
> result value of "fopen". Again, I would use a "TYPE(C_PTR),VALUE" which
> reflects the black box best. But using an INTEGER(c_intptr_t),VALUE should
> also work. (Cf. above for "fopen".)

Ok, using TYPE(c_ptr) here, too.


However, when the test case is updated accordingly (see attachment), I
also end up with a valgrind error on Linux:

 #1
 #2
==19696== Invalid read of size 8
==19696==    at 0x5B17062: ferror (in /lib64/libc-2.17.so)
==19696==    by 0x4E3F097: BZ2_bzReadOpen (in /usr/lib64/libbz2.so.1.0.6)
==19696==    by 0x400B9F: MAIN__ (testBz2.f90:38)
==19696==    by 0x400C3C: main (testBz2.f90:42)
==19696==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==19696==

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.



> But there are surely more problems. In particular: bzReadOpen reads much
> more argument values from the stack than you put there.

I'm not sure I understand what you mean ...

Cheers,
Janus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testBz2.f90
Type: application/octet-stream
Size: 1036 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/fortran/attachments/20130601/d6ea4061/attachment.obj>


More information about the Fortran mailing list