urbanjost / M_system

Call C system routines (mostly POSIX) from Fortran
The Unlicense
15 stars 2 forks source link

Funny behavior with -finit-local-zero #4

Open burp opened 3 years ago

burp commented 3 years ago

When compiling the Fortran code with -finit-local-zero, the statement integer(kind=c_long),bind(c,name="longest_env_variable") :: longest_env_variable

instantiates the variable:

% gfortran -finit-local-zero -c M_system.f90 % readelf -s M_system.o | grep longest 41: 0000000000000448 8 OBJECT GLOBAL HIDDEN 4 longest_env_variable

% gfortran -c M_system.f90 % readelf -s M_system.o | grep longest 41: 0000000000000008 8 OBJECT GLOBAL HIDDEN COM longest_env_variable

and therefore, if you want to link the C and Fortran code you end up with a "multiple definitions" error.

I suppose that the answer to this issue is, in principle, to not compile with -finit-local-zero. In practice it's often a hassle to build individual files with different flags.

The gcc manual reads "The -finit-local-zero option instructs the compiler to initialize local INTEGER, REAL, and COMPLEX variables to zero". Apparently this also applies to variables that are bound to C objects.

The issue also applies to FHOST_NAME_MAX.

I am not sure whether you consider this an issue of the compiler, or my attempt in using your library with -finit-local-zero. But if we could come up with a solution that works with and without -finit-local-zero that might be good?

urbanjost commented 3 years ago

Well, at least with gfortran you can do

gfortran -finit-local-zero  -Wl,--allow-multiple-definition ..

and tell the loader to take the first definition and ignore duplicates. I really do not think that this variable should be considered "local" though. I am wondering what other compilers with a similar option do; but have just switched machines and so far do not have anything else except GCC. I am thinking that is a bug in that anything declared bound to C objects should not be classified as "local" but have not found a strict definition of the term in the GCC documentation so far. I am waffling on whether I think this is a bug or not. I do not knowof anything that explicitly says you cannot initialize C-bound objects and do not get any errors if I explicitly set an initial value by adding "=0" to the declaration. I am not sure why I am setting it the way I am in the C code, but there are notes in the code about having trouble with gfortran 6.4.0 with one of the variables. It is unconditionally set to a large value by initenv(3c) which should have been sufficient; I think I was kludging the C code to get around some compiler issues. Once I get nvfortran and ifort on my new box I am going to try a more straight-forward C interface. In the mean time (especially since the load-time value is ignored) using the loader switch should get you going.

urbanjost commented 3 years ago

Was not thinking about the other variables; ones set in C and not initialized to 0 are probably not "first" so ignorning duplicates probably means everything needs set to the correct value in Fortran or overridden at run-time in C. "first" is the kicker here.