1

Our C++ application, running on Linux and compiled with gcc, loads dynamic libraries as 'plugins'. The code is well-established and runs fine with gcc 5.3.1. However, with gcc 7.3.0, library loading is failing at runtime. We get 'symbol not found' errors such as:

Failed to load <snip>/solibs/_gnuRelease/libLink.so
dlerror = <snip>: undefined symbol: _ZN24ChannelSelection7INVALIDE ( ChannelSelection::INVALID )
Failed to load <snip>/solibs/_gnuRelease/libBitTrue.so
dlerror = <snip>: undefined symbol: _ZTIN8StarLibs7LinkSim8StarFPGAE ( typeinfo for StarLibs::LinkSim::StarFPGA )

(Demangled symbol name is in parentheses).

Has anything changed in gcc 7.3.0 that might cause this?

DavidA
  • 2,053
  • 6
  • 30
  • 54
  • 2
    Maybe the obvious question first: are those symbols actually present in your .so files? – Botje Dec 06 '18 at 10:31
  • Yes, sorry that is the obvious question. So for missing symbol _ZN24ChannelSelection7INVALIDE, that symbol is not in the library file for gcc 5.3 and 7.3 builds, build only the 7.3 build complains about it. The actual definition of the symbol is static const int INVALID = -1; Could there something special about a static symbol that is causing a problem? – DavidA Dec 06 '18 at 10:59
  • From what I could [find](https://stackoverflow.com/questions/16957458/static-const-in-c-class-undefined-reference/16957554), what you are seeing is not bound to the compiler per se, but how the constant is used, eg in the standard library. GCC 6 started compiling code as C++14 by default, which may enable a different overload that needs the address of your constant (`const int&`, for example). Short version: Can you try compiling your code with `-std=gnu++98`, which was the pre-GCC6 default? – Botje Dec 06 '18 at 12:03
  • I have tried -std=gnu++98 and the build works ok. So, as you predicted, it is related to C++11 or C++14 being used. Not sure what to do about it. I do want to use C++11 later. – DavidA Dec 06 '18 at 12:10
  • If you can jump directly to C++17, you can declare your static const ints as `constexpr` or `inline` and the compiler will generate it with external linkage (defining a symbol). Until then, you can choose to explicitly provide symbols in a .cpp file like so: `const int ChannelSelection::INVALID;` – Botje Dec 06 '18 at 12:20
  • Thank you. I have explicitly provided the symbols in the .cpp file as you suggested. That has fixed the issue. – DavidA Dec 06 '18 at 15:35
  • If you copy your comment to an answer I will accept it. – DavidA Dec 06 '18 at 15:46

1 Answers1

0

If you can jump directly to C++17, you can declare your static const ints as constexpr or inline and the compiler will generate it with external linkage (defining a symbol).

Until then, you can choose to explicitly provide symbols in a .cpp file like so:

const int ChannelSelection::INVALID;
Botje
  • 26,269
  • 3
  • 31
  • 41