I'm sorry about the vagueness of this post, but I'm not able to share the code, and anyway, it would be too much to share anyway.
I have this shared library, "shared", which is loaded by another library. The problem is that when loading the shared library, I get the error message saying "undefined symbol: _ZplPKcRK18ExampleClass"
The problem I have is that ExampleClass is declared and defined in the shared library. I made sure that I the ExampleClass is properly defined, and that the .h and .cpp are actually getting compiled.
I'm really confused about this, so any insight would be really helpful.
I'm building using cmake 3.6.2 and gcc 4.8.5 on CentOS 7.
This is a problem that usually occurs when loading in a shared library and then trying to code from that library. Since linking of the library did not happen directly after compile time, you will not get any linker errors that would be associated with the file and what is dynamically loading it. Look into a demangler(c++filt) and try to get more information about what that "_ZplPKcRK18ExampleClass" references.
In my experience, it is usually something along the lines of a method signature mismatch and the code does not know where to branch after the library is loaded.
Related
I'm attempting to write a wrapper library and compile it to a shared object in order to access various C functions in my C# application necessary to communicate with a piece of hardware. (following this tutorial initally https://www.olegtarasov.me/build-cross-platform-c-library/)
When I build the shared object, even though it compiles I run into a missing symbol issue with various functions related to "bcm_host.h". For other missing symbols I've been able to include the .c files where the functions are housed, but for bcm_host.h there aren't .c files storing the functions that I can find.
Reading online people solve seem to solve this issue by installing missing kernel headers (https://raspberrypi.stackexchange.com/questions/36121/fatal-error-bcm-host-h-no-such-file-or-directory-compilation-terminated)
However following these steps doesn't solve my issue. I've downloaded the library that holds the various files including bcm_host.h,
and included bcm_host.h which solves my issue with the compiling, but again, when any function is called that attempts to access these methods I hit a missing symbol error.
Is there an issue with the way that I'm linking headers? So far I've had to link .c files in order to have their functions properly map to address spaces once the library is built.
I'm sure I'm missing something quite obvious to someone who knows this area better than I do, any help would be greatly appreciated.
I have inherited a code project that contains several individual libraries of code that compile separately and then are linked in the compiled tools. It's supposed to be a Chinese menu of what each tool wants. This all written on Linux, in C++, with Qt. There are several issues with the current design, but I'm learning to deal.
This latest issue has me really dumbfounded. The main library is the Utilities. It contains a handful of classes and it compiles into a .a library file. Another library is our DatabaseInterfaces. It has class files that refer to header files from Utilities (they are all shared) but the CPP files are not included in DatabaseInterfaces. DatabaseInterfaces also compiles into a .a library. Finally, we have a CMDPrompt tool that imports both the Utilities.a and DatabaseInterfaces.a libraries. CMDPrompt does not compile. Instead, I get several errors indicating that I have an undefined reference for one of the objects in Utilities.
After several different attempts to fix this, I finally directly included the CPP file in the CMDPrompt.pro. It worked or at least it is now finding new undefined references for other classes in Utilities. This confirms to me that somehow the projects are not linking correctly. I would have expected that because the Utilities library is linked in I would have gotten all of the H/CPP goodness with it. I suspect the problem is that the DatabaseInterfaces library is compiling against the H files only and needs the same Utilities.a library. I tried adding that LIB into the DatabaseInterfaces.pro, but it didn't have any effect.
I am not a C++ programmer by training and while I believe I understand the main points of the linking process, I am obviously missing something. Here are my questions. Given the relationship between the different libraries, how should the linker work? Why is the DatabaseInterfaces.a compiling at all with just the H files? What is the best way to resolve this issue?
You need to link the libraries in the right order - it sounds like Utilities.a needs to be linked last. I don't know how you do that in Qt but that's what you need to achieve.
Consider the following code structure:
main.cpp -> depends on libone.a -> depends on libtwo.a
Assume that in main.cpp only functions from libone.a are used. So realistically the programmer writing main.cpp really only cares about libone.a. At this point they don't even know libone.a has a dependency on libtwo.a.
They attempt to compile their code as follows and get linker errors:
g++ -o main main.cpp -lone
-- Error! Undefined symbols!
This becomes an issue because since libone.a depends on libtwo.a, anyone who uses libone.a must know about this dependency... As you can imagine this problem can occur with FAR more dependencies than a single library and can quickly become a linking nightmare.
Attempt 1 at solving this issue:
A first thought to solve this issue was "It's simple, i'll just link libone.a with libtwo.a when I compile libone.a!
It turns out it isn't as simple as I had hoped... When compiling libone.a there is no way to link libtwo.a. Static libraries don't link to anything when you compile them, instead all of the dependencies must be linked when the libraries are compiled into an executable.
For example, to compile main.cpp that depends on a static library that in turn depends on another static library, you must link both libraries. ALWAYS.
g++ -o main main.cpp -lone -ltwo
Attempt 2 at solving this issue:
Another thought was to try and compile libone as a dynamic library that links to libtwo.a.
Oddly enough this just worked! After compiling and linking libone.so the main program only needs to care about libone.so and doesn't need to know about libtwo.a anymore.
g++ -o main main.cpp -lone
Success!
After going through this exercise one piece is still missing. I just can't seem to figure out any reason why static libraries can't link in other libraries, but dynamic ones can. As a matter of fact, the dynamic library, libone.so would not compile at all until I linked libtwo.a. That's fine though, because as the author of libone.so I would know about its dependency on libtwo.a - The author of main.cpp, however would not know. And realistically they should not have to know.
So down to the real question... Why can dynamic libraries link to other libraries like this while static ones cannot? This seems to be an obvious advantage dynamic libraries have over static ones, but I've never seen it mentioned anywhere!
A static library is just an archive of object files, there is no concept of dependency because it was never linked.
Shared libraries are linked, solving symbols, and they can have, as such, dependencies.
Since your question refers to gcc and .so/.a files, I’ll assume you’re using some flavor of Unix that uses ELF files for object code.
After going through this exercise one piece is still missing. I just
can't seem to figure out any reason why static libraries can't link in
other libraries, but dynamic ones can.
Static libraries are not linked, as was mentioned in another answer. They are just an archive of compiled object files. Shared libraries are in fact linked, which means the linker actually resolves all the symbols reachable by any exported symbol. Think of exported symbols as the library’s API. A fully linked shared library contains either the definition of each symbol, or the dependency information necessary to tell the OS (specifically the dynamic loader) what other shared libraries are needed to have access to the symbol. The linker assembles all that into a special file format called an ELF shared object (dynamic library).
As a matter of fact, the dynamic library, libone.so would not compile
at all until I linked libtwo.a. That's fine though, because as the
author of libone.so I would know about its dependency on libtwo.a -
The author of main.cpp, however would not know. And realistically they
should not have to know.
libone.so probably compiles fine, but won’t link without libtwo due to unresolved symbols. Because the linker must resolve all reachable symbols when linking a shared library, it will fail if it can’t find any. Since libone.so uses symbols in libtwo, the linker needs to know about libtwo.a to find them. When you link a static library into a shared library, the symbols are resolved by copying the definitions directly into the output shared object file, so at this point, users of libone.so can be none the wiser about its usage of libtwo since its symbols are just in libone.so.
The other option is to link shared libraries into other shared libraries. If you are linking libtwo.so into libone.so (note the .so suffix), then the linker resolves the symbols needed by libone by adding a special section to the output shared object file that says it needs libtwo.so at runtime. Later, when the OS loads libone.so, it knows it also needs to load libtwo.so. And, if your application only uses libone directly, that’s all you need to tell the linker at build time, since it’ll link in libone, see that it needs libtwo, and recursively resolve until everything is good.
Now, all that loading at runtime the OS has to do incurs a performance cost, and there are some gotchas with global static variables that exist in multiple shared objects if you aren’t careful. There are some other potential performance benefits for linking statically that I won’t go into here, but suffice it to say that using dynamic libraries isn’t quite as performant on average, but that difference is also negligible for most real world situations.
I've got a project working on that's using FreeImage and openCV, currently we're using the jpeg support from both of these (I am working towards fixing that, but for now it's got to stay). Anyhow, FreeImage compiles libjpeg 7.0 into its static libraries, and openCV's highgui library links it in as a shared library (on my system, Ubuntu 9, I've got libjpeg 6.2 installed).
They link into a final library that's used to link into various programs, java wrappers, etc. All of that works fine, no symbol conflicts or anything during compile/link time. However, when I go to open an image using the openCV cvLoadImage function, it dies when reading the header, most likely due to differences between headers in 6.2 and 7.0.
If I unlink FreeImage (and comment out the code that requires it), the openCV calls start working again, so clearly the static libjpeg symbols from FreeImage are conflicting with symbols that would be loaded from the libjpeg shared library. What I can't figure out is why my compiler isn't throwing an error during linking because of the two sets of libjpeg symbols. Additionally, I've tried replacing my system's jpeglib.h header with the 7.0 version temporarily to see if openCV compiled with that would then sync up with the symbols that freeimage brings to the table, to no avail it seems.
Lastly I put a printf in jpeg_read_header in the libjpeg that freeimage compiles, and rebuilt it to see if openCV is using the freeimage libjpeg definition. It didn't print out so I have to assume not.
So I guess my questions are
1) Why doesn't linking a static libjpeg and a shared libjpeg generate linking errors due to duplicate symbols?
2) Does anyone know why these two things are conflicting with one another?
Edit: Compiling openCV in debug mode and then in regular mode again seems to have knocked something loose and made it work again, no idea what's going on.
Generally speaking the linker is fine about being passed multiple libraries that all resolve the same symbol(s). It just uses the first one it finds. The order of the libraries on your linker command line will determine which one "wins".
This, by the way, is NOT true of object files. Every linker I've ever used assumes that you want to use all of the objects that you specify, and will complain if more than one has the same symbol.
You need to modify the linking options to export only the symbols that you want, then all the symbols in conflict will be hidden internally in the static linking, then no conflicts. By default all the symbols are exported, that's the problem. See this link: http://www.gnu.org/software/gnulib/manual/html_node/Exported-Symbols-of-Shared-Libraries.html
it is like this
Static libraries are compiled in, dynamic libraries are loaded during runtime, but only those symbols which are missing (I think). you can compile shared libraries in, and then you probably get symbol collision.
so opencv uses symbols which are compiled in, since they already present, rather than those from dynamic libraries. you end up using static symbols, possibly with different signatures, from prospective of opencv.
I'm trying to build a very complex open-source project with VC++. The project consists of dozens of libraries and one executable depending on those libraries.
For some reasons VC++ linker doesn't want to see about 40 functions implemented in one of those libraries and reports "unresolved external reference" on each, so I can't link. I don't want to waste time resolving the problem - those functions are likely never called.
I'd like to just ask the linker to link what it sees and insert some reasonable error handling (like reporting an error and terminating the program) instead of missing functions. How can I do that?
You can use the /FORCE:UNRESOLVED linker option.
The documentation for that contains the rather understated warning:
A file created with this option may
not run as expected.
In pratice, there'll be no error handling - just a crash.
If the functions are truly never called, then create actual libraries (.lib files) for the libraries. Then the linker will only extract from the libraries what's needed.
The linker's job is to resolve all references, so I don't think you're going to get it to insert error handling code.
P.S. The first thing I'd check is to see if C functions got compiled as C++, leading to the missing symbols.
If they're never called, remove the references from your project. If they are called, then fix the damn problem. There's no real other option here.
There are some notable exceptions, but most OpenSource projects are not designed to be built under VisualStudio.
Generally for a Windows port you are better off using either cygwin or the mingw system. My advice is usually for mingw, unless the program uses a lot of Unix OSey calls like pipes and signals.