Best practices for debugging linking errors - c++

When building projects in C++, I've found debugging linking errors to be tricky, especially when picking up other people's code. What strategies do people use for debugging and fixing linking errors?

Not sure what your level of expertise is, but here are the basics.
Below is a linker error from VS 2005 - yes, it's a giant mess if you're not familiar with it.
ByteComparator.obj : error LNK2019: unresolved external symbol "int __cdecl does_not_exist(void)" (?does_not_exist##YAHXZ) referenced in function "void __cdecl TextScan(struct FileTextStats &,char const *,char const *,bool,bool,__int64)" (?TextScan##YAXAAUFileTextStats##PBD1_N2_J#Z)
There are a couple of points to focus on:
"ByteComparator.obj" - Look for a ByteComparator.cpp file, this is the source of the linker problem
"int __cdecl does_not_exist(void)" - This is the symbol it couldn't find, in this case a function named does_not_exist()
At this point, in many cases the fastest way to resolution is to search the code base for this function and find where the implementation is. Once you know where the function is implemented you just have to make sure the two places get linked together.
If you're using VS2005, you would use the "Project Dependencies..." right-click menu. If you're using gcc, you would look in your makefiles for the executable generation step (gcc called with a bunch of .o files) and add the missing .o file.
In a second scenario, you may be missing an "external" dependency, which you don't have code for. The Win32 libraries are often times implemented in static libraries that you have to link to. In this case, go to MSDN or "Microsoft Google" and search for the API. At the bottom of the API description the library name is given. Add this to your project properties "Configuration Properties->Linker->Input->Additional Dependencies" list. For example, the function timeGetTime()'s page on MSDN tells you to use Winmm.lib at the bottom of the page.

One of the common linking errors I've run into is when a function is used differently from how it's defined. If you see such an error you should make sure that every function you use is properly declared in some .h file.
You should also make sure that all the relevant source files are compiled into the same lib file. An error I've run into is when I have two sets of files compiled into two separate libraries, and I cross-call between libraries.
Is there a failure you have in mind?

The C-runtime libraries are often the biggest culprit. Making sure all your projects have the same settings wrt single vs multi-threading and static vs dll.
The MSDN documentation is good for pointing out which lib a particular Win32 API call requires if it comes up as missing.
Other than that it usually comes down to turning on the verbose flag and wading through the output looking for clues.

Related

Error LNK2019 when trying to use MRPT libraries as external dependency in VS2019 solution

I am implementing a SLAM-algorithm in Visual Studio 2019 where I want to use the ICP algorithm from the MRPT library for scan-matching.
I installed the MRPT library as 32-bit from source code using CMake. Problem is the error I'm receiving when building the solution (shown below). I assume it is because I have not added Additional Library Directories or Additional Dependencies for the Linker, because I can't find the .lib/.dll files anywhere. I tried installing the 64-bit precompiled binaries for Windows, where I found the .lib-files inside a lib-folder which does not appear when compiling manually with the source code - but can't use the same lib's because I need 32-bit (I tried linking to them, but the same error occurred in addition a bunch of warnings that library is 64-bit and target is 32-bit).
The code is pretty much exactly the same as the first example here, with (I believe) all necessary headers included.
The error produced (I also receive many more of the same error for every class I attempt to use from the library):
particle.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall mrpt::poses::CPose2D::CPose2D(double,double,double)" (__imp_??0CPose2D#poses#mrpt##QAE#NNN#Z) referenced in function (function)
The quick question is: Shouldn't the .lib/.dll files be produced when compiling from source code as well? Or is there something embedded in the library so I don't need them, in which case there must be something else wrong?
The more complicated question is: If the missing .dll/.lib-files is not the problem, what could it be?
Sorry if I am missing any relevant information, this is my first post. Just let me know and I will provide.
Any help is greatly appreciated!

C++ .dll adding in Visual Studio - yet another "unresolved external symbol"

I am adding .dll to C++ project.
IDE: Visual Studio 2013
What I did:
Added directory with headers to VC++ Directories -> Include Directories
. It's ok, I can include headers, IntellySense sees names
in these files.
Added .lib file to Additional Dependencies section and a path to this
file in both VC++ Directories -> Library Directories and Linker -> General -> Additional Library Directories.
Placed actual .dll file to DEBUG folder (also to project folder, just
to be sure)
Used dumpbin.exe to get sure I have exported all needed classes in my
.dll
And I still get a bunch of unresolved externals with functions stored in that .dll. Any suggestions?
I found this question and set Use library Dependency Inputs to Yes. Still no luck.
Some more info:
Error example:
Error 2 error LNK2019: unresolved external symbol "__declspec(dllimport) public: double __thiscall Fem::Node::GetX(void)" (__imp_?GetX#Node#Fem##QAENXZ) referenced in...
This function in dumpbin output:
172 AB 000F81A0 ?GetX#Node#Fem##QEAANXZ
I see some difference in the last part of the name. Somehow, as I mentioned in the comments, I got it working in Qt project with Visual Studio compiler.
This is usually a bad idea, since it doesn't lead to a reusable library. The application can't be rebuilt with a new compiler or even new compile settings without also rebuilding the DLL. It is safer to just compile the classes you use in statically. That said, there are some benefits if used in conjunction with delay-loading, so...
In order to store a class implementation in a DLL, while building the DLL you must use __declspec(dllexport) on the class, and when consuming it there must be __declspec(dllimport). Import libraries have shims to forward free function references to DLLs but those don't work for classes and class members.
Usually macros are used to accomplish the switch between dllexport and dllimport.
Now that you've shown mangled names, the difference becomes apparent, and demangling gives a clue to where the problem came from.
Linker is looking for
public: double __thiscall Fem::Node::GetX(void)
But DLL is exporting
public: double __cdecl Fem::Node::GetX(void) __ptr64
Notice that the calling conventions are different; if this had linked, you would have crashed as soon as you tried to call this function.
You cannot use exports from a DLL that have C++ signatures from an application compiled differently. Are you mixing architectures (x86 vs x86_64 vs ARM)? Can't do that either, not even using highly-compatible C calling signatures.

Linker error while building CUDA/C++ code

I get the following error while trying to build a CUDA/C++ code in Visual Studio 2012. I'm using CUDA v5.0
1> Generating Code...
1>LINK : warning LNK4044: unrecognized option '/MLd'; ignored
1>cublas_device.lib(kepler_sm35_gemm_wrapper.obj) : error LNK2019: unresolved external symbol __cudaRegisterLinkedBinary_59_tmpxft_00001040_00000000_8_kepler_sm35_gemm_wrapper_cpp1_ii_9402ff4f referenced in function "void __cdecl __sti____cudaRegisterAll_59_tmpxft_00001040_00000000_8_kepler_sm35_gemm_wrapper_cpp1_ii_9402ff4f(void)" (?__sti____cudaRegisterAll_59_tmpxft_00001040_00000000_8_kepler_sm35_gemm_wrapper_cpp1_ii_9402ff4f##YAXXZ)
Anybody has any idea of where the problem might be? I've tried googling around, but haven't found a solution for this as yet.
Thanks a lot!
This article shows information about what the /MLd linker option does. It essentially has to do with multithreaded libs being loaded and the configuration of your project.
Is your (Debug) project set up to link with the microsoft linker or nvcc? (The error messages appear to be coming from the microsoft linker.) You may want to look at this question
Device code and device libraries (that you are linking against) need to be linked with nvcc.
You need to link against the debug version of the CUDA library. You try to compile in Debug mode, but then you link against a library which seems not to have been built in debug mode. Thus it gets all messed up.
So you should either get the .lib file for the debug version, or build it yourself if you have the source code. Then you link your debug build with the debug .lib and same for release.
Also, it may help that you use the same version of the compiler to build all libs, otherwise you may run into name mangling issues (which could be also a potential cause for your problem). It happened to me after switching to a newer VS version: I had to recompile all the .lib I was linking against.
It looks like some sort of using a external (extern) variable that isn't defined. The code is required for further information
I was able to fix it! I was linking to cublas_device.lib which was referring to an unresolved external symbol. However, this lib file wasn't required by my project, so just removing it from the linked files worked! However, in Release mode this error wasn't happening - maybe because this part of the code in cublas_device.lib was in the debug section.
In any case, since it is not required by my project, removing it solves the problem.
Thanks a lot for all your replies!
I encountered the same issue, Changing the Configuration Type from "Dynamic library (dll)" to "Static library (lib)" worked for me.

C++ Project compiles as static lib, fails (linker error) as dynamic lib. why?

I've a VS2008 native C++ project, that I wish to compile as a DLL.
It only references one external library (log4cplus.lib), and uses its functions.
(also uses log4cplus's .h files , naturally).
When I try to compile my project as a static library, it succeeeds.
When I try as DLL, it fails :
1>MessageWriter.obj : error LNK2019: unresolved external symbol "public: static class log4cplus::Logger __cdecl log4cplus::Logger::getInstance(class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > const &)" (?getInstance#Logger#log4cplus##SA?AV12#ABV?$basic_string#_WU?$char_traits#_W#std##V?$allocator#_W#2##std###Z) referenced in function "class log4cplus::Logger __cdecl Log(void)" (?Log##YA?AVLogger#log4cplus##XZ)
There are 4 more errors just like this related to functions within log4cplus.lib.
It seems like something really stupid.. please help me :)
Thanks!
Edit :
I am linked against the log4cplus.lib file, and it finds it just fine.
also, the log4cplus.lib is 100% functional, I am using it in another project with no problems.
My original intention was to compile my project as a static library and use it in another DLL I am writing, but when do this, I get the same linker errors in that other project...
Edit #2 :
The functions which cause the linker errors are static functions.. could this be part of the problem?
wilx is right.I have the same link problem.
it took me almost one day to slove this issue.
I have downloaded log4cplus-1.0.4, after I opened this project with visual studio 2010,compile it, both static and dynamic library, no error.
however, when I try to use those library, I got a link error,no matter static library or dynamic library.
the reason is,by default, those project use multi-byte character, however, my own project use unicode,so,to slove those link problem, you just need to change one project's charset.
both unicode or both multi-byte charset.
and to change one project's charset in visual studio 2010,
see the following link.
How do I turn off Unicode in a VC++ project?
When you're creating a static library, the library creator does not try to resolve all the functions that you are using (the ones that are in log2cplus.lib). These functions are resolved when you create an executable that links with your static library.
When you're creating a dynamic library, the library creator (the linker) does try to resolve all the functions you are using. You have to provide the linker with the log4cplus.lib library as soon as you build the dynamic library. You cannot wait until you create the executable.
In either case you need to link against library.
Difference is that when you link statically - all functionality is linked via library you're using.
When you're linking dynamically you link against import library which have functionality to load and use functions from dll and this step you're missing. Usually import library have the same name as the dll you're linking against.
Edit:
I saw it that missing symbol is not '__imp...'
This means that header file is not "configured" for dynamic linkage, probably because you have LOG4CPLUS_BUILD_DLL or log4cplus_EXPORTS or DLL_EXPORT not defined in project where you include Log4Cplus headers.
Are you actually linking with the log2cplus.lib file? If you were compiling as a static library then you would link to it via the final .exe and not in the static library - perhaps that is the difference?
Did you use __declspec(dllimport) and __declspec(dllexport)?
They are not necessary when linking static libraries, but required for DLLs. The function has to be declared for exporting (in the DLL), so users can use it outside (and thus import it from the DLL).
Maybe this can help:
Importing into an Application Using __declspec(dllimport)
http://msdn.microsoft.com/en-us/library/8fskxacy%28VS.80%29.aspx
best regards
If you're using a compiler like MSVC, then it may have changed the project settings without you knowing about it when changing from lib to dll. You should double-check that in DLL mode, you are properly linked to the lib.
There are two possibilities that I can see for the linker error:
You have compiled the log4cplus.dll (and the associated log4cplus.lib import library) using the provided Release build configuration but now your application is compiled with "Character Set" option set to "Use Unicode Character Set"
Or you are trying to use log4cplus' static library but defining LOG4CPLUS_BUILD_DLL for your application.
I bet on number 1. It could be something else, still. What version of log4cplus are you using?
If you want to use log4cplus.dll in your application, define the LOG4CPLUS_BUILD_DLL symbol. log4cplus_EXPORTS and DLL_EXPORT are there only to support the CMake based build system, and autotools based build system on MingGW respectively.

Link Error : xxx is already defined in *****.LIB :: What exactly is wrong?

Problem:
I'm trying to use a library named DCMTK which used some other external libraries ( zlib, libtiff, libpng, libxml2, libiconv ). I've downloaded these external libraries (*.LIB & *.h files ) from the same website. Now, when I compile the DCMTK library I'm getting link errors (793 errors) like this:
Error 2 error LNK2005: __encode_pointer already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Error 3 error LNK2005: __decode_pointer already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Error 4 error LNK2005: __CrtSetCheckCount already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Error 5 error LNK2005: __invoke_watson already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Error 6 error LNK2005: __errno already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Error 7 error LNK2005: __configthreadlocale already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Error 8 error LNK2005: _exit already defined in MSVCRTD.lib(MSVCR90D.dll) LIBCMTD.lib dcmmkdir
Documentation:
This seems to be a popular error for this library so, they do have a FAQ entry addressing this issue which ( http://forum.dcmtk.org/viewtopic.php?t=35 ) says:
The problem is that the linker tries to combine different,
incompatible versions of the Visual
C++ runtime library into a single
binary.
This happens when not all parts of your project and the libraries you
link against are generated with the
same code generation options in Visual
C++.
Do not use the /NODEFAULTLIB workaround, because strange software
crashes may follow. Fix the problem!
DCMTK is by default compiled with the "Multithreaded" or "Multithreaded
Debug" code generation option (the
latter for Debug mode).
Either change the project settings of all of your code to use these code
generation options,
or change the code generation for all DCMTK modules and re-compile.
MFC users beware: DCMTK should be compiled with "Multithreaded DLL" or
"Multithreaded DLL Debug" settings if
you want to link the libraries into an
MFC application.
Solution to same problem for others:
Huge Amount of Linker Issues with Release Build Only says:
It seems that your release build is
trying to link to something that was
built debug. You probably have a
broken dependency in your build, (or
you missed rebuilding something to
release by hand if your project is
normally built in pieces).
More technically, you seem to be
linking projects built with different
C Run Time library settings, one
with "Multi-Threaded", another one
with "Multi-Threaded Debug". Adjust
the settings for all the projects to
use the very same flavour of the
library and the issue should go away
Questions:
Till now I used to think that Name mangling is the only problem that may cause linking failures if its not been standardized. Just now I knew there are other things also which can cause same effect.
Whats up with the "Debug Mode" (Multi-Threaded Debug) and "Release Mode" (Multi-Threaded)? What exactly is happening under the hood? Why exactly this thing is causing linking error?
I wonder if there is something called "Single-Threaded Debug" and "Single-Threaded" which again causes the same thing.
Documentation talks something about "Code Generation Options". What Code Generation Options? WTH are they?
Documentation specifically warns us not to use /NODEFAULTLIB workaround. (example /NODEFAULTLIB :msvcrt ). Why? How would I cause troubles? what exactly is it?
Please explain the last point in the documentation for MFC users. Because I'm going to use MFC later in this project. Explain Why should we do it? What troubles would it cause if I don't.
Anything more you'd like to mention? I mean regarding similar errors. I'm very interested in Linker & its problems. So, if there are any similar things you can mentions them or some keywords atleast.
Whats up with the "Debug Mode"
(Multi-Threaded Debug) and "Release
Mode" (Multi-Threaded)? What exactly
is happening under the hood? Why
exactly this thing is causing linking
error?
The linker drags in libraries for several different reasons. The simplest is that a library is listed on the linker command line, or in the linker answer file on the linker command line. But any object files, whether compiled in your project or packed into a library, can also contain linker options including requesting particular libraries be linked in. In fact, the Visual C++ compiler automatically embeds such linker options matching the project options you use when compiling.
At link time, all the linker options from all object files and objects in static library files get combined. If more than one CRT library filename is requested, the linker reads in all of them and them you get naming conflicts, where the linker doesn't know which one to use.
I wonder if there is something called
"Single-Threaded Debug" and
"Single-Threaded" which again causes
the same thing.
There used to be, but the last few versions of Visual C++ have only shipped multi-thread compatible libraries.
Documentation talks something about
"Code Generation Options". What Code
Generation Options? WTH are they?
Look inside your project options.
Documentation specifically warns us
not to use /NODEFAULTLIB workaround.
(example /NODEFAULTLIB :msvcrt ). Why?
How would I cause troubles? what
exactly is it?
If you use /NODEFAULTLIB, all the linker settings stored within object files and objects in libraries get ignored. You'll end up with no runtime library and maybe missing other libraries. You can add them back in by hand, but it's still a big mess.
Please explain the last point in the
documentation for MFC users. Because
I'm going to use MFC later in this
project. Explain Why should we do it?
What troubles would it cause if I
don't. Anything more you'd like to
mention? I mean regarding similar
errors. I'm very interested in Linker
& its problems. So, if there are any
similar things you can mentions them
or some keywords atleast.
MFC applications and the MFC library have to use the same memory management functions, so that memory allocated by MFC can be freed by the application and vice-versa. FILE handles and other resources are also shared. The MFC DLLs are already compiled to use the CRT in a DLL, and in order to be able to share resources you need to use the same CRT, which means using a DLL too.
You need to configure project properties so that your debug build links with DCMTK's debug build and your release build links with DCMTK's release build.
The above is what you need to do. Below are explanations of some other random things you asked about.
Older versions of Visual Studio used to have single threaded libraries (release and debug versions) besides multithreaded libraries (release and debug versions). For your project you can pretend single threaded libraries never existed.
If you experiment with random ways to trick the linker into shutting up and leaving problems to be found by your customers instead of by yourself, you might find that the /NODEFAULTLIB option will do that. The makers of the DCMTK library are warning you not to do that because some other people did the same dumb thing in the past.
Whats up with the "Debug Mode" (Multi-Threaded Debug) and "Release Mode" (Multi-Threaded)? What exactly is happening under the hood? Why exactly this thing is causing linking error?
They are different versions of the C runtime library. You can statically link to the runtime library in debug and release mode. In the Code Generation Options (mentioned below), those would be "Multi-Threaded Debug" and "Multi-Threaded". The options "Multi-Threaded Debug DLL" and "Multi-Threaded DLL" dynamically link to the C runtime. By dynamically linking to the runtime, you'll also have to ship your installer configured to install the VC redistributable package that contains the proper runtime dlls for your version of Visual C++.
Statically linking to the C runtime is generally frowned upon, even by Microsoft:
In addition to all the methods
described above of distributing the
Visual C++ libraries DLLs, there is
one last option for building your
application which does not require you
to distribute the DLLs. However, this
option only works for native-only code
(it is not supported with /clr) and
leaves your customers seriously
vulnerable to any security holes as
well as adds a significant burden upon
yourself to patch all customer systems
should a vulnerability be found in any
of the libraries. This option is to
statically link in the libraries as
.lib files instead of dynamically
loading them as DLLs. You do this by
using the /MT flag on the cl.exe
command line (vs /MD), or selecting
the appropriate option in your project
properties through Visual Studio. You
may wish to use this option when
testing early debug builds of your
application on test machines before
you start working on setup. [See
footnote 3]
However, I can think of no scenarios
in which this is actually the right
thing to do when shipping your product
to customers. Basically, what this
approach does is pulls in the binary
code needed from .LIB files at compile
time, making it a part of your .exe or
.dll files. It increases the size of
your application, and there is no way
to update the libraries apart from
recompiling your application with new
.LIBs and redistributing your
application all over again. What this
means is that unless you go touch
every single machine which has
installed your application every time
there is a security vulnerability
found in the Visual C++ libraries and
completely reinstall your updated
binaries, you will be leaving your
customers vulnerable to attack. If
instead you use the DLLs, every time
there is a security vulnerability
found in the Visual C++ libraries,
Microsoft will install the update
centrally into the WinSxS folder via
Windows Update and all requests for
the DLLs will be redirected to the
updated version. This removes all
servicing burden on your side and also
allows the user to install one small
update which will touch all their
applications instead of replacing
every installed exe and DLL on their
system. Please, do not distribute an
application built by linking
statically against the Visual C++
libraries unless you have a system in
place for updating every customer
machine and also have a very good
reason to do so. At this time, I can
think of no circumstance under which
this would be the right thing to do
for a shipping application.
I wonder if there is something called
"Single-Threaded Debug" and
"Single-Threaded" which again causes
the same thing.
No such thing, see above.
Documentation talks something about "Code Generation Options". What Code Generation Options? WTH are they?
Right click on your Visual C++ project (from within Visual Studio) and select Properties. Under Configuration Properties->C/C++->Code Generation
Documentation specifically warns us not to use /NODEFAULTLIB workaround. (example /NODEFAULTLIB :msvcrt ). Why? How would I cause troubles? what exactly is it?
Take their advice and don't do it.
Please explain the last point in the documentation for MFC users. Because I'm going to use MFC later in this project. Explain Why should we do it? What troubles would it cause if I don't.
Because MFC is dynamically linked to the C runtime, using libraries that are statically linked to the C runtime will cause the linker errors you listed first in your post.
Anything more you'd like to mention? I mean regarding similar errors. I'm very interested in Linker & its problems. So, if there are any similar things you can mentions them or some keywords atleast.
From my experience, always dynamically link to the C runtime. It generally saves you a lot of headaches like the one you're experiencing right now.