# Duplicate symbols - how to trace where these are coming from?

**URL:** <https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915>\
**Category:** Help\
**Created:** [April 26, 2024, 2:51pm UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915 "2024-04-26T14:51:43Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [April 26, 2024, 2:51pm UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/1 "2024-04-26T14:51:43Z")

</div>

I have just run into a conundrum: in a large program I have to include a call to an extra subroutine. But if I do that I all of a sudden get error messages two symbols are duplicately defined. As all routines are contains in modules I am rather surprised at that and the error messages point to libraries that do not directly contain these symbols. How can I find out where these symbols are coming from? Right now I have a hard time figuring out what to do.

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [April 26, 2024, 3:09pm UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/2 "2024-04-26T15:09:12Z")

</div>

Not sure how your object files and libraries are structured but on Linux I would try using nm to list symbols in object files. I would probably write all the .o files generated into one directory and then use ar to build a static library. Then use nm with grep to try to narrow down where the symbols are occuring. I doubt this is fool proof but in the absence of compiler options to build a cross-reference of symbols (something old time compilers like the UNIVAC compilers would do for you) I’m unaware of a more automated way of finding duplicate symbols. They probably exist and I’m just not aware of them.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 26, 2024, 3:21pm UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/3 "2024-04-26T15:21:55Z")

</div>

Qualifying `use` statements with `only` could fix the problem or help to diagnose it. For example, the following program

```auto
module kind_mod
implicit none
integer, parameter :: wp = kind(1.0d0)
end module kind_mod
!
module sub_mod
implicit none
integer, parameter :: wp = kind(1.0d0)
contains
subroutine hi()
print*,"hi"
end subroutine hi
end module sub_mod
!
program main
use kind_mod
use sub_mod
implicit none
call hi()
print*,"wp =",wp
end program main

```

does not compile, with gfortran saying

```auto
xxmod.f90:20:16:

   20 | print*,"wp =",wp
      | 1
Error: Name 'wp' at (1) is an ambiguous reference to 'wp' from module 'kind_mod'

```

If `use sub_mod` is replaced with `use sub_mod, only: hi` the problem is solved, and if

```auto
use kind_mod
use sub_mod

```

are replaced with

```auto
use kind_mod, only: wp
use sub_mod, only: wp, hi

```

the problem is apparent.

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [April 26, 2024, 8:26pm UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/4 "2024-04-26T20:26:52Z")

</div>

I have been thinking about that sort of methods and causes. As it is this one routine that causes the problem, it should be straightforward to find the underlying cause. However, it is the _linker_ that complains, not the compiler. And right now I am suspicious about the “!DEC$ ATTRIBUTES DLLEXPORT” statements in the implementation of the two routines that figure in the “duplicate symbols” error. The names in these messages changed, when I removed their “bind(C)” attributes.

Well, weekend now. Time enough next week for renewed worrying.

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [April 27, 2024, 1:05am UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/5 "2024-04-27T01:05:04Z")

</div>

Depending on your platform there are typically options to display the origin point of symbols. For example, on a Linux system with gfortran and the ld loader the gfortran option

```bash
-Wl,--trace-symbol=foo

```

added to the gfortran(1) command will show the files foo is defined in.

ld(1) has many useful options. The man-page describes them in detail.

For example, this program calls SIN(). What file is SIN() defined in?

```fortran
program testit
   write(*,*)sin(0.0)
end program testit

```

```bash
 gfortran xx.f90 -Wl,--trace-symbol=sin

```

```plaintext
 /usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: definition of sin
 /usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: definition of sin

```

nm(1), ldd(1) ,objdump(1),readelf(1),ar(1), and strings(1) can also be useful.

You can allow multiple definitions to not be an error as well.

```bash
# allow multiple definitions; NOTE: make sure the one you want is loaded first
gfortran xx.f90 -Wl,--trace-symbol=sin,--allow-multiple-definition

```

```bash
# list all the libraries used on the load
gfortran xx.f90 -Wl,--trace|sort|uniq|cat -n

```

When you get a list of all file files loaded you can then use file-oriented commands  
like nm(1) on the files of interest.

```plaintext
     1 /dev/shm/cceZr6TL.o
     2 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
     3 /lib/x86_64-linux-gnu/libc.so.6
     4 /lib/x86_64-linux-gnu/libm.so.6
     5 /lib/x86_64-linux-gnu/libmvec.so.1
     6 /usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o
     7 /usr/lib/gcc/x86_64-linux-gnu/13/crtendS.o
     8 /usr/lib/gcc/x86_64-linux-gnu/13/libgcc.a
     9 /usr/lib/gcc/x86_64-linux-gnu/13/libgcc_s.so
    10 /usr/lib/gcc/x86_64-linux-gnu/13/libgfortran.so
    11 /usr/lib/gcc/x86_64-linux-gnu/13/libquadmath.so
    12 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crti.o
    13 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/crtn.o
    14 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/libc.so
    15 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/libgcc_s.so.1
    16 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/libm.so
    17 /usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/Scrt1.o
    18 /usr/lib/x86_64-linux-gnu/libc_nonshared.a

```

There are other very powerful options like --swap=symbol which among other things lets you call custom versions to trap out-of-range values or record malloc() calls too. MSWindows users might like --force-exe-suffix; and so on but those get into other topics.

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [April 29, 2024, 6:53am UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/6 "2024-04-29T06:53:30Z")

</div>

My development platform is Windows (though Linux is the second on which it should all work). The curious thing is that the linker complains about two routines with names of the form MODULENAME\_mp\_SUBROUTINE (note the capitals). Before, with the BIND(C) clause in effect, the names were “subroutine”(so, lowercase). These names are getting in independently of the USE statement.

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [April 29, 2024, 6:56am UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/7 "2024-04-29T06:56:58Z")

</div>

It definitely has to do with the “!DEC$ ATTRIBUTES DLLEXPORT” directive. Commenting that out solves the problem (but other programs in the VS solution do need them). I guess splitting off the culprits into a separate source file and ditto module might help here.

---

<div class="post-metadata">

**Author:** ![davidpfister](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/davidpfister/32/3949_2.png) [@davidpfister](https://fortran-lang.discourse.group/u/davidpfister)\
**Post date:** [April 29, 2024, 7:37am UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/8 "2024-04-29T07:37:21Z")

</div>

I had some similar issues in the past when working on Windows. Maybe what you could try is to remove the ‘bind(C)’ and define your interface more explicitly:

```auto
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, ALIAS: "subroutine" :: subroutine

```

In addition, if your code does not always require the DLLEXPORT, and that you are not completely hostile to preprocessing, you could play with preprocessor variable to have a conditional export. Personally, I am using this kind of approach for my unit tests. Usually I would compile test cases as dll, and my test driver loads them and call the exported tests subroutines. But, when using fpm for instance, I also use the tests cases statically, and in this case I do not export them.

```auto
#ifndef _NOEXPORT
    !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, ALIAS: "test_1" :: test_1
#endif

```

The only issue with this approach is that you need to make sure to recompile all your objects because sometimes the linker would complain about subroutines with stdcall convention when statically bound to the main program.

---

<div class="post-metadata">

**Author:** ![DavidB](https://avatars.discourse-cdn.com/v4/letter/d/76d3ee/32.png) [@DavidB](https://fortran-lang.discourse.group/u/DavidB)\
**Post date:** [April 29, 2024, 11:07pm UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/9 "2024-04-29T23:07:19Z")

</div>

> [@Arjen](#):
>
> Before, with the BIND(C) clause in effect, the names were “subroutine”(so, lowercase).

The BIND(C) statement changes the name used by the linker/loader, particularly with optional “NAME=” specifier. I think it is working as expected.

Can you share your full “!DEC$ ATTRIBUTES DLLEXPORT” directive. An ALIAS in this directive may duplicate the symbol name in the BIND(C). I am unclear what happens when you use both, and don’t have time to experiment today.

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [April 30, 2024, 6:21am UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/10 "2024-04-30T06:21:31Z")

</div>

Sure, here are the lines of code for one of them:

```auto
subroutine set_progress_c_callback(c_callback) bind(C, name="set_progress_c_callback")
#ifdef _WIN32
  !DEC$ ATTRIBUTES DLLEXPORT:: set_progress_c_callback
#endif

I figured out that this directive was the culprit because the name of the duplicate symbol changed with removing the bind() attribute.

```

---

<div class="post-metadata">

**Author:** ![davidpfister](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/davidpfister/32/3949_2.png) [@davidpfister](https://fortran-lang.discourse.group/u/davidpfister)\
**Post date:** [April 30, 2024, 7:00am UTC](https://fortran-lang.discourse.group/t/duplicate-symbols-how-to-trace-where-these-are-coming-from/7915/11 "2024-04-30T07:00:17Z")

</div>

@Arjen, you are definitely not the only one to experience strange thing with dll export 🤔. I copy here a comment from another post:

> [@A long-standing bug in a gtk-fortran example with Intel compilers](https://fortran-lang.discourse.group/t/a-long-standing-bug-in-a-gtk-fortran-example-with-intel-compilers/5734/2):
>
> I use “!DEC$ ATTRIBUTES STDCALL,REFERENCE,ALIAS:‘hello’, DLLEXPORT :: hello” for intel, so to enable using both you would need a macro like:
> 
> ```auto
> #ifdef __GNUC__
> !GCC$ ATTRIBUTES DLLEXPORT :: hello
> #else
> !DEC$ ATTRIBUTES STDCALL,REFERENCE,ALIAS:'hello', DLLEXPORT :: hello
> #endif
> 
> ```
> 
> the directives should be OS agnostic

And this one is from the [intel forum](https://community.intel.com/t5/Intel-Fortran-Compiler/fortran-calling-C-stdcall-and-cdecl/m-p/1202106/highlight/true#M151361):

> What you are seeing is that MSVC is ALSO emitting a name without the suffix - and Intel Fortran does this too. Why? Fortran does it because that allows you to declare a name simply EXTERNAL and pass it as an argument. I am not sure why MSVC is doing it as well.

It may be that when you mix bind(c) and !DEC$ directives the compiler gets ‘confused’ and exports twice the subroutine.  
Can you make a dump of the .lib using dumpbin? (dumpbin /exports \*\*.lib)?
