Linker Cannot Find Symbols, But Libraries Are Read and Symbols Exist

Linker cannot find symbols, but libraries are read and symbols exist

You have to put the libraries' linker flags after the object files. So, instead of

g++ -o installertest \
-lsybdb \
-lxmlrpc \
-lxmlrpc_cpp \
-lxmlrpc_xmlparse \
-lxmlrpc_xmltok \
-lxmlrpc_util \
-lxmlrpc++ \
-lxmlrpc_server_cgi \
-lssl \
-std=c++0x \
ContractData.o installertest.o

use

g++ -o installertest \
ContractData.o installertest.o \
-lsybdb \
-lxmlrpc \
-lxmlrpc_cpp \
-lxmlrpc_xmlparse \
-lxmlrpc_xmltok \
-lxmlrpc_util \
-lxmlrpc++ \
-lxmlrpc_server_cgi \
-lssl \
-std=c++0x

Linker reads library but can't find symbol within it? Unresolved External Symbol but only for Win32 and not x64


 9    8 00001389 _swe_close@0 = @ILT+900(_swe_close@0)

There's a clear mismatch between the function name in the DLL and the one that the linker is looking for. The DLL project has it compiled to an __stdcall function, you can tell from the @0 decoration, the linker is looking for a __cdecl function.

That can be caused by a compiler option, /Gd vs /Gz but that's unlikely and you already checked it. The more likely cause is the .h file where the exported functions are declared so that another project can #include it and use the DLL. That's usually done with macro soup so that the __declspec(dllexport) and __declspec(dllimport) attributes are correct for usage. And the calling convention should always be explicitly declared, typically with another macro. Like the way the WINAPI macro is used in Windows SDK headers. I'll put a buck on that soup being the cause.

linker tells me it can't resolve symbols, but they're there?

Change:

g++ -g3 -Wall -I"../../" -lrt -lroller -o rap main.o

to:

g++ -g3 -Wall main.o -lroller -lrt -o rap 

Link order matters (and the -I is redundant in this instance).

`ld` undefined reference error, but libraries are linked to by CMake and symbols exist


Fix /h3>

The cause of the linker errors was this statement:

if(LINUX)

The fix was to replace it with this:

if(UNIX AND NOT APPLE)

This commit fixes the problem:

Commit

Reference: https://stackoverflow.com/a/40152725/3405291

Strangely, CMake wasn't complaining about anything and just throwing random linker errors.

GCC and ld can't find exported symbols...but they're there

the U before _ZN3lib-namespace12GetStatusStrEi in the nm output shows that the symbol is undefined in the library.

Maybe it's defined in the wrong namespace: it looks like you're calling it in lib-namepace but you might be defining it in another.

gcc - A static library with undefined symbols?


Why does the static (.a) lib have dependencies on shared objects (e.g. libopenssl) that aren't statically compiled?

Just about every static library that you can build will have unresolved symbols, e.g.

int my_open_for_read(const char *filename)
{
return open(filename, O_RDONLY); // unresolved reference to open
}

As Marc Glisse pointed out, this a plain unresolved symbol, not a dependency on libc.so.


  1. How do I solve this?

There is no problem to solve here. When you link your binary, you get to decide which libraries to link statically, and which to link dynamically.

Trying to manually add -lssl doesn't seem to work.

This should work:

gcc main.o -lthis -lssl

Possibly you did something like

gcc main.o -lssl -lthis

which is wrong: the order of libraries on the link line matters.

How do I get the binary to compile and not have external dependcies?

Most OSes support using fully-static binaries. Generally this should not be your goal: it makes for less portable binaries, and their use is strongly discouraged.

If you really do want to produce a fully-static binary, link it with -static flag.

Why do you say full static is less portable?

Because they are.

if the user doesn't have the exact same build of the lib, the binary won't be portable with shared libs, but will be portable with static.

This is incorrect: most shared libraries support backward compatibility, e.g. libc.so.6 version 2.22 will happily run executables linked against version 2.3.6 from 10 years ago.

If you do ldd firefox

You need to pay attention to what you are doing:

file -L `which /usr/bin/firefox`
/usr/bin/firefox: POSIX shell script, ASCII text executable

If you look inside the shell script, you'll discover that it invokes /usr/lib/firefox/firefox, and that binary is dynamically linked:

ldd /usr/lib/firefox/firefox
linux-vdso.so.1 => (0x00007ffca278d000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f511731b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5117117000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5116e13000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5116b0d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f51168f7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5116532000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5117757000)

symbols not found in static library even though they are there

The function you need is SGBucket::gen_base_path[abi:cxx11]() const.

The function you have is SGBucket::gen_base_path() const. These aren't the same symbol.

You can use -Wl,--no-demangle at link time to tell the linker to print mangled (real) symbol that ends up undefined, and that would make it clearer that you don't in fact have a definition of that symbol.

Possibly the libSimGearCore.a library was compiled without -std=c++11 flag, while the code which needs the symbol was compiled with it.

Boost.DLL cannot find symbols in executable using statically linked library

boost::DLL works only with exported symbols. Your symbols are not exported. "Exporting" symbols is something that is outside the scope of the C++ language. It needs to be done with __declspec(dllexport) or similar.

Statically linked symbols are not accessible at runtime. The linker discards them.


The error says "B_SIZE" not found. B_SIZE is defined in B.cpp as

const size_t B_SIZE = sizeof(B);

This symbol is never exported. It is linked statically to your .exe and it's definition will then be discarded.

You probably could change this to

const size_t __declspec(dllexport) B_SIZE = sizeof(B);

to force it to be exported (although exporting a variable as opposed to a function comes with it's own problems). Then, in theory, the compiler should tag it as "export this" and the lib command ar should honor this information as it builds the static lib "B.o"

Finally, when the implicit linker call in your g++ -Wall ... exe -lB command get's executed, the linker should bind the static lib "B.o" to your exe, find the "please export me" flag and copy the symbol information for B_SIZE to the .exe.

Only if you export a symbol, the info will be written to the .dll. Then other programs will be able to look it up.


One more thing, hidden in the boost DLL tutorial. Under Windows, __declspec(dllexport) will export the symbols even for a .EXE file. So if you statically link your B.o to the .EXE, the windows tools will honor the dllexport tag and export the symbol. That's true for Microsoft and similar linkers.

The small note in the tutorial regarding linux says, you have to pass -rdynamic to the linux linker. I am guessing here, but since exporting symbols from a .EXE is unusual (standard is .DLL), the linux tools might ignore all dllexport tags and explicitly hide exported symbols from the runtime - unless you explicitly tell them to include them, which is what -rdynamic could be for.


BTW, the way this is usually done is like this:

#if defined(MYLIB_EXPORTS)
#define MYLIB_API __declspec(dllexport)
#else if defined(MYLIB_IMPORTS)
#define MYLIB_API __declspec(dllimport)
#else
#define MYLIB_API /* */
#endif

void MYLIB_API B_get(void*);


Related Topics



Leave a reply



Submit