Where is "first defined here"?

I have a fortran 77 (fixed format) program and gfortran returns the following message when I try to compile it:

/usr/bin/ld: /tmp/cc5N4OCb.o:(.bss+0x820): multiple definition of `newshr_'; /tmp/ccKFhng4.o:(.data+0x8700): first defined here

“newshr” is a common block used in nearly every subroutine (there are scores). What does “here” mean in the context of “first defined here”? I expect it has to do with +0x820 or +0x8700 - is there a way to get a listing file showing what those addresses correspond to? Is this gfortran’s way of complaining that the common block length is not consistent across all subroutines? Is a “common” statement in a subroutine a “definition” or is a definition something that happens in block data? Is this a complaint that newshr is in two block data routines? I don’t think it is.

The problem seems to go away if I change the extension from .f to .for which would seem to contradict both of my theories but it returns if I give the compiler each subroutine in a separate file instead of concatenating them into a single file before giving the code to the compiler.

Any help much appreciated.

I imagine there are two data statements in separate object files which initialize the same block.

C gds100.f
      subroutine gds100
      character(20) :: ebuf
      common /gdscb2/ ebuf
      data ebuf /"abcdef"/
      end
C gds102.f
      subroutine gds102
      character(20) :: ebuf
      common /gdscb2/ ebuf
      data ebuf /"abcdef"/
      end
C driver.f
      external gds100, gds102
      call gds100
      call gds102
      end

This gives me a linking error:

$ gfortran driver.f gds100.f gds102.f
duplicate symbol '_gdscb2_' in:
    /var/folders/5h/txm_8yhd2n721_w7gsrvlkj8p3bpj9/T//ccJdcC1o.o
    /var/folders/5h/txm_8yhd2n721_w7gsrvlkj8p3bpj9/T//cceFW49s.o
ld: 1 duplicate symbol for architecture x86_64
collect2: error: ld returned 1 exit status

The long names are temporary files created by the compiler driver. Compiling to object files in the current folder first, makes this more obvious:

$ gfortran -c gds100.f gds102.f
$ gfortran driver.f gds100.o gds102.o
duplicate symbol '_gdscb2_' in:
    gds100.o
    gds102.o
ld: 1 duplicate symbol for architecture x86_64
collect2: error: ld returned 1 exit status

To fix the error one of the data statements needs to be removed. The results I’m showing are from a Mac so the system linker may be different from what you are using.

If I put everything in the same translation unit, the linking error dissappears, and the first data initialization prevails (not obvious here):

C all_in_one.f

      subroutine gds100
      character(20) :: ebuf
      common /gdscb2/ ebuf
      data ebuf /"abcdef"/
      end

      subroutine gds102
      character(20) :: ebuf
      common /gdscb2/ ebuf
      data ebuf /"abcdef"/
      write(*,'(A)') trim(ebuf)
      end

      external gds100, gds102
      call gds100
      call gds102
      end
$ gfortran all_in_one.f 
$ ./a.out
abcdef

I’m pretty sure that all of the data statements need to be removed. It is not legal to initialize a variable in a common block with a data statement in a subprogram, and the reason is exactly what is happening here. The only legal way to initialize a common block variable is in a block data unit.

I say “pretty sure” because this might have changed in some recent fortran revisions. But I would say, even if it has changed, it is still a terrible programming practice. If you insist on using common blocks, then go ahead and use block data to initialize them. If you convert them to modules, then the variables may be initialized in the usual way, and there is no danger of multiple initializations.

I’ll also comment that the error occurs at the linking (ld) stage, and not compiling.

Indeed, the standard says (emphasis mine):

C808 (R803) An initialization shall not appear if object-name is a dummy argument, a function result, an object in a named common block unless the type declaration is in a block data program unit, an object in blank common, an allocatable variable, or an automatic data object.

I’ll also note that both COMMON and block data program units are obsolescent.

In fact I did not even suspect that the program was attempting to initialize common block data outside of a block data statement, so thoroughly had I absorbed this lesson decades ago.

But this error can make it into a gfortran executable without even a warning, unless -pedantic is specified.

By separating the compile and link steps I was able to find the offending code before I thought to use the -pedantic option. Thank you for that advice.

Thanks to everyone
Daniel Feenberg