What is an undefined reference/unresolved external symbol error and how do I fix it?


What are undefined reference/unresolved external symbol errors? What are common causes and how to fix/prevent them?



Feel free to edit/add your own.



Compiling a C++ program takes place in several steps, as specified by 2.2 (credits to Keith Thompson for the reference):



The precedence among the syntax rules of translation is specified by the following phases [see footnote].



[footnote] Implementations must behave as if these separate phases occur, although in practice different phases might be folded together.



The specified errors occur during this last stage of compilation, most commonly referred to as linking. It basically means that you compiled a bunch of implementation files into object files or libraries and now you want to get them to work together.



Say you defined symbol a in a.cpp. Now, b.cpp declared that symbol and used it. Before linking, it simply assumes that that symbol was defined somewhere, but it doesn't yet care where. The linking phase is responsible for finding the symbol and correctly linking it to b.cpp (well, actually to the object or library that uses it).



If you're using Microsoft Visual Studio, you'll see that projects generate .lib files. These contain a table of exported symbols, and a table of imported symbols. The imported symbols are resolved against the libraries you link against, and the exported symbols are provided for the libraries that use that .lib (if any).



Similar mechanisms exist for other compilers/ platforms.



Common error messages are error LNK2001, error LNK1120, error LNK2019 for Microsoft Visual Studio and undefined reference to symbolName for GCC.



The code:



will generate the following errors with GCC:



and similar errors with Microsoft Visual Studio:



Common causes include:



Declaring a destructor pure still requires you to define it (unlike a regular function):



This happens because base class destructors are called when the object is destroyed implicitly, so a definition is required.



This is similar to non-virtual methods with no definition, with the added reasoning that
the pure declaration generates a dummy vtable and you might get the linker error without using the function:



For this to work, declare X::foo() as pure:



Some members need to be defined even if not used explicitly:



The following would yield the error:



The implementation can be inline, in the class definition itself:



or outside:



If the implementation is outside the class definition, but in a header, the methods have to be marked as inline to prevent a multiple definition.



All used member methods need to be defined if used.



The definition should be



An initializer can be provided for a static const data member of integral or enumeration type within the class definition; however, odr-use of this member will still require a namespace scope definition as described above. C++11 allows initialization inside the class for all static const data members.



Commonly, each translation unit will generate an object file that contains the definitions of the symbols defined in that translation unit.
To use those symbols, you have to link against those object files.



Under gcc you would specify all object files that are to be linked together in the command line, or compile the implementation files together.



The libraryName here is just the bare name of the library, without platform-specific additions. So e.g. on Linux library files are usually called libfoo.so but you'd only write -lfoo. On Windows that same file might be called foo.lib, but you'd use the same argument. You might have to add the directory where those files can be found using -L‹directory›. Make sure to not write a space after -l or -L.



For XCode: Add the User Header Search Paths -> add the Library Search Path -> drag and drop the actual library reference into the project folder.



Under MSVS, files added to a project automatically have their object files linked together and a lib file would be generated (in common usage). To use the symbols in a separate project, you'd
need to include the lib files in the project settings. This is done in the Linker section of the project properties, in Input -> Additional Dependencies. (the path to the lib file should be
added in Linker -> General -> Additional Library Directories) When using a third-party library that is provided with a lib file, failure to do so usually results in the error.



It can also happen that you forget to add the file to the compilation, in which case the object file won't be generated. In gcc you'd add the files to the command line. In MSVS adding the file to the project will make it compile it automatically (albeit files can, manually, be individually excluded from the build).



In Windows programming, the tell-tale sign that you did not link a necessary library is that the name of the unresolved symbol begins with __imp_. Look up the name of the function in the documentation, and it should say which library you need to use. For example, MSDN puts the information in a box at the bottom of each function in a section called "Library".



A typical variable declaration is



As this is only a declaration, a single definition is needed. A corresponding definition would be:



For example, the following would generate an error:



Similar remarks apply to functions. Declaring a function without defining it leads to the error:



Be careful that the function you implement exactly matches the one you declared. For example, you may have mismatched cv-qualifiers:



Other examples of mismatches include



The error message from the compiler will often give you the full declaration of the variable or function that was declared but never defined. Compare it closely to the definition you provided. Make sure every detail matches.



The order in which libraries are linked DOES matter if the libraries depend on each other. In general, if library A depends on library B, then libA MUST appear before libB in the linker flags.



For example:



Create the libraries:



Compile:



So to repeat again, the order DOES matter!



what is an "undefined reference/unresolved external symbol"



I'll try to explain what is an "undefined reference/unresolved external symbol".



note: i use g++ and Linux and all examples is for it



For example we have some code



and



Make object files



After the assembler phase we have an object file, which contains any symbols to export.
Look at the symbols



I've rejected some lines from output, because they do not matter



So, we see follow symbols to export.



src2.cpp exports nothing and we have seen no its symbols



Link our object files



and run it



Linker sees exported symbols and links it. Now we try to uncomment lines in src2.cpp like here



and rebuild an object file



OK (no errors), because we only build object file, linking is not done yet.
Try to link



It has happened because our local_var_name is static, i.e. it is not visible for other modules.
Now more deeply. Get the translation phase output



So, we've seen there is no label for local_var_name, that's why linker hasn't found it. But we are hackers :) and we can fix it. Open src1.s in your text editor and change



to



i.e. you should have like below



we have changed the visibility of local_var_name and set its value to 456789.
Try to build an object file from it



ok, see readelf output (symbols)



now local_var_name has Bind GLOBAL (was LOCAL)



link



and run it



ok, we hack it :)



So, as a result - an "undefined reference/unresolved external symbol error" happens when the linker cannot find global symbols in the object files.



The function (or variable) void foo() was defined in a C program and you attempt to use it in a C++ program:



The C++ linker expects names to be mangled, so you have to declare the function as:



Equivalently, instead of being defined in a C program, the function (or variable) void foo() was defined in C++ but with C linkage:



and you attempt to use it in a C++ program with C++ linkage.



If an entire library is included in a header file (and was compiled as C code); the include will need to be as follows;



If all else fails, recompile.



I was recently able to get rid of an unresolved external error in Visual Studio 2012 just by recompiling the offending file. When I re-built, the error went away.



This usually happens when two (or more) libraries have a cyclic dependency. Library A attempts to use symbols in B.lib and library B attempts to use symbols from A.lib. Neither exist to start off with. When you attempt to compile A, the link step will fail because it can't find B.lib. A.lib will be generated, but no dll. You then compile B, which will succeed and generate B.lib. Re-compiling A will now work because B.lib is now found.



MSVS requires you to specify which symbols to export and import using __declspec(dllexport) and __declspec(dllimport).



This dual functionality is usually obtained through the use of a macro:



The macro THIS_MODULE would only be defined in the module that exports the function. That way, the declaration:



expands to



and tells the compiler to export the function, as the current module contains its definition. When including the declaration in a different module, it would expand to



and tells the compiler that the definition is in one of the libraries you linked against (also see 1)).



You can similary import/export classes:



Unspecialized templates must have their definitions visible to all translation units that use them. That means you can't separate the definition of a template
to an implementation file. If you must separate the implementation, the usual workaround is to have an impl file which you include at the end of the header that
declares the template. A common situation is:



To fix this, you must move the definition of X::foo to the header file or some place visible to the translation unit that uses it.



Specialized templates can be implemented in an implementation file and the implementation doesn't have to be visible, but the specialization must be previously declared.



For further explanation and another possible solution (explicit instantiation) see this question and answer.



This is one of most confusing error messages that every VC++ programmers have seen time and time again. Let’s make things clarity first.



A. What is symbol?
In short, a symbol is a name. It can be a variable name, a function name, a class name, a typedef name, or anything except those names and signs that belong to C++ language. It is user defined or introduced by a dependency library (another user-defined).



B. What is external?
In VC++, every source file (.cpp,.c,etc.) is considered as a translation unit, the compiler compiles one unit at a time, and generate one object file(.obj) for the current translation unit. (Note that every header file that this source file included will be preprocessed and will be considered as part of this translation unit)Everything within a translation unit is considered as internal, everything else is considered as external. In C++, you may reference an external symbol by using keywords like extern, __declspec (dllimport) and so on.



C. What is “resolve”?
Resolve is a linking-time term. In linking-time, linker attempts to find the external definition for every symbol in object files that cannot find its definition internally. The scope of this searching process including:



This searching process is called resolve.



D. Finally, why Unresolved External Symbol?
If the linker cannot find the external definition for a symbol that has no definition internally, it reports an Unresolved External Symbol error.



E. Possible causes of LNK2019: Unresolved External Symbol error.
We already know that this error is due to the linker failed to find the definition of external symbols, the possible causes can be sorted as:



For example, if we have a function called foo defined in a.cpp:



In b.cpp we want to call function foo, so we add



to declare function foo(), and call it in another function body, say bar():



Now when you build this code you will get a LNK2019 error complaining that foo is an unresolved symbol. In this case, we know that foo() has its definition in a.cpp, but different from the one we are calling(different return value). This is the case that definition exists.



If we want to call some functions in a library, but the import library is not added into the additional dependency list (set from: Project | Properties | Configuration Properties | Linker | Input | Additional Dependency) of your project setting. Now the linker will report a LNK2019 since the definition does not exist in current searching scope.



undefined reference to WinMain@16 or similar 'unusual' main() entry point reference (especially for visual-studio).



You may have missed to choose the right project type with your actual IDE. The IDE may want to bind e.g. Windows Application projects to such entry point function (as specified in the missing reference above), instead of the commonly used int main(int argc, char** argv); signature.



If your IDE supports Plain Console Projects you might want to choose this project type, instead of a windows application project.



Also if you're using 3rd party libraries make sure you have the correct 32/64 bit binaries



Microsoft offers a #pragma to reference the correct library at link time;



In addition to the library path including the directory of the library, this should be the full name of the library.



Visual Studio NuGet package needs to be updated for new toolset version



I just had this problem trying to link libpng with Visual Studio 2013. The problem is that the package file only had libraries for Visual Studio 2010 and 2012.



The correct solution is to hope the developer releases an updated package and then upgrade, but it worked for me by hacking in an extra setting for VS2013, pointing at the VS2012 library files.



I edited the package (in the packages folder inside the solution's directory) by finding packagenamebuildnativepackagename.targets and inside that file, copying all the v110 sections. I changed the v110 to v120 in the condition fields only being very careful to leave the filename paths all as v110. This simply allowed Visual Studio 2013 to link to the libraries for 2012, and in this case, it worked.



Suppose you have a big project written in c++ which has a thousand of .cpp files and a thousand of .h files.And let's says the project also depends on ten static libraries. Let's says we are on Windows and we build our project in Visual Studio 20xx. When you press Ctrl + F7 Visual Studio to start compiling the whole solution ( suppose we have just one project in the solution )



What's the meaning of compilation ?



The Second step of compilation is done by Linker.Linker should merge all the object file and build finally the output ( which may be an executable or a library)



Steps In Linking a project



Observation



How To Solve this kind of error



Compiler Time Error :



Linker Time Error



I recently had this problem, and it turned out it was a bug in Visual Studio Express 2013. I had to remove a source file from the project and re-add it to overcome the bug.



Steps to try if you believe it could be a bug in compiler/IDE:



Linked .lib file is associated to a .dll



I had the same issue. Say i have projects MyProject and TestProject. I had effectively linked the lib file for MyProject to the TestProject. However, this lib file was produced as the DLL for the MyProject was built. Also, I did not contain source code for all methods in the MyProject, but only access to the DLL's entry points.



To solve the issue, i built the MyProject as a LIB, and linked TestProject to this .lib file (i copy paste the generated .lib file into the TestProject folder). I can then build again MyProject as a DLL. It is compiling since the lib to which TestProject is linked does contain code for all methods in classes in MyProject.



Most modern linkers include a verbose option that prints out to varying degrees;



For gcc and clang; you would typically add -v -Wl,--verbose or -v -Wl,-v to the command line. More details can be found here;



For MSVC, /VERBOSE (in particular /VERBOSE:LIB) is added to the link command line.



Since people seem to be directed to this question when it comes to linker errors I am going to add this here.



One possible reason for linker errors with GCC 5.2.0 is that a new libstdc++ library ABI is now chosen by default.



If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.



So if you suddenly get linker errors when switching to a GCC after 5.1.0 this would be a thing to check out.



A wrapper around GNU ld that doesn't support linker scripts



Some .so files are actually GNU ld linker scripts, e.g. libtbb.so file is an ASCII text file with this contents:



Some more complex builds may not support this. For example, if you include -v in the compiler options, you can see that the mainwin gcc wrapper mwdip discards linker script command files in the verbose output list of libraries to link in. A simple work around is to replace the linker script input command file with a copy of the file instead (or a symlink), e.g.



Or you could replace the -l argument with the full path of the .so, e.g. instead of -ltbb do /home/foo/tbb-4.3/linux/lib/intel64/gcc4.4/libtbb.so.2



Given the code snippet of a template type with a friend operator (or function);



The operator<< is being declared as a non-template function. For every type T used with Foo, there needs to be a non-templated operator<<. For example, if there is a type Foo<int> declared, then there must be an operator implementation as follows;



Since it is not implemented, the linker fails to find it and results in the error.



To correct this, you can declare a template operator before the Foo type and then declare as a friend, the appropriate instantiation. The syntax is a little awkward, but is looks as follows;



The above code limits the friendship of the operator to the corresponding instantiation of Foo, i.e. the operator<< <int> instantiation is limited to access the private members of the instantiation of Foo<int>.



Alternatives include;



Allowing the friendship to extend to all instantiations of the templates, as follows;



Or, the implementation for the operator<< can be done inline inside the class definition;



Note, when the declaration of the operator (or function) only appears in the class, the name is not available for "normal" lookup, only for argument dependent lookup, from cppreference;



A name first declared in a friend declaration within class or class template X becomes a member of the innermost enclosing namespace of X, but is not accessible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at the namespace scope is provided...



There is further reading on template friends at cppreference and the C++ FAQ.



Code listing showing the techniques above.



As a side note to the failing code sample; g++ warns about this as follows



warning: friend declaration 'std::ostream& operator<<(...)' declares a non-template function [-Wnon-template-friend]



note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)



A Windows UNICODE build is built with TCHAR etc. being defined as wchar_t etc. When not building with UNICODE defined as build with TCHAR defined as char etc. These UNICODE and _UNICODE defines affect all the "T" string types; LPTSTR, LPCTSTR and their elk.



Building one library with UNICODE defined and attempting to link it in a project where UNICODE is not defined will result in linker errors since there will be a mismatch in the definition of TCHAR; char vs. wchar_t.



The error usually includes a function a value with a char or wchar_t derived type, these could include std::basic_string<> etc. as well. When browsing through the affected function in the code, there will often be a reference to TCHAR or std::basic_string<TCHAR> etc. This is a tell-tale sign that the code was originally intended for both a UNICODE and a Multi-Byte Character (or "narrow") build.



To correct this, build all the required libraries and projects with a consistent definition of UNICODE (and _UNICODE).



This can be done with either;



Or in the project settings;



Project Properties > General > Project Defaults > Character Set



Or on the command line;



The alternative is applicable as well, if UNICODE is not intended to be used, make sure the defines are not set, and/or the multi-character setting is used in the projects and consistently applied.



Do not forget to be consistent between the "Release" and "Debug" builds as well.



A "clean" of the build can remove the "dead wood" that may be left lying around from previous builds, failed builds, incomplete builds and other build system related build issues.



In general the IDE or build will include some form of "clean" function, but this may not be correctly configured (e.g. in a manual makefile) or may fail (e.g. the intermediate or resultant binaries are read-only).



Once the "clean" has completed, verify that the "clean" has succeeded and all the generated intermediate file (e.g. an automated makefile) have been successfully removed.



This process can be seen as a final resort, but is often a good first step; especially if the code related to the error has recently been added (either locally or from the source repository).



Examples are in C. They could equally well be C++



my_lib.c



my_lib.h



eg1.c



You build your static library:



You compile your program:



You try to link it with libmy_lib.a and fail:



The same result if you compile and link in one step, like:



eg2.c



Compile your program:



Try to link your program with libz and fail:



Same if you compile and link in one go:



And a variation on example 2 involving pkg-config:



In the sequence of object files and libraries you want to link to make your
program, you are placing the libraries before the object files that refer to
them. You need to place the libraries after the object files that refer
to them.



Link example 1 correctly:



Success:



Link example 2 correctly:



Success:



Link the example 2 pkg-config variation correctly:



Reading is optional from here on.



By default, a linkage command generated by GCC, on your distro,
consumes the files in the linkage from left to right in
commandline sequence. When it finds that a file refers to something
and does not contain a definition for it, to will search for a definition
in files further to the right. If it eventually finds a definition, the
reference is resolved. If any references remain unresolved at the end,
the linkage fails: the linker does not search backwards.



First, example 1, with static library my_lib.a



A static library is an indexed archive of object files. When the linker
finds -lmy_lib in the linkage sequence and figures out that this refers
to the static library ./libmy_lib.a, it wants to know whether your program
needs any of the object files in libmy_lib.a.



There is only object file in libmy_lib.a, namely my_lib.o, and there's only one thing defined
in my_lib.o, namely the function hw.



The linker will decide that your program needs my_lib.o if and only if it already knows that
your program refers to hw, in one or more of the object files it has already
added to the program, and that none of the object files it has already added
contains a definition for hw.



If that is true, then the linker will extract a copy of my_lib.o from the library and
add it to your program. Then, your program contains a definition for hw, so
its references to hw are resolved.



When you try to link the program like:



the linker has not added eg1.o to the program when it sees
-lmy_lib. Because at that point, it has not seen eg1.o.
Your program does not yet make any references to hw: it
does not yet make any references at all, because all the references it makes
are in eg1.o.



So the linker does not add my_lib.o to the program and has no further
use for libmy_lib.a.



Next, it finds eg1.o, and adds it to be program. An object file in the
linkage sequence is always added to the program. Now, the program makes
a reference to hw, and does not contain a definition of hw; but
there is nothing left in the linkage sequence that could provide the missing
definition. The reference to hw ends up unresolved, and the linkage fails.



Second, example 2, with shared library libz



A shared library isn't an archive of object files or anything like it. It's
much more like a program that doesn't have a main function and
instead exposes multiple other symbols that it defines, so that other
programs can use them at runtime.



Many Linux distros today configure their GCC toolchain so that its language drivers (gcc,g++,gfortran etc)
instruct the system linker (ld) to link shared libraries on an as-needed basis.
You have got one of those distros.



This means that when the linker finds -lz in the linkage sequence, and figures out that this refers
to the shared library (say) /usr/lib/x86_64-linux-gnu/libz.so, it wants to know whether any references that it has added to your program that aren't yet defined have definitions that are exported by libz



If that is true, then the linker will not copy any chunks out of libz and
add them to your program; instead, it will just doctor the code of your program
so that:-



At runtime, the system program loader will load a copy of libz into the
same process as your program whenever it loads a copy of your program, to run it.



At runtime, whenever your program refers to something that is defined in
libz, that reference uses the definition exported by the copy of libz in
the same process.



Your program wants to refer to just one thing that has a definition exported by libz,
namely the function zlibVersion, which is referred to just once, in eg2.c.
If the linker adds that reference to your program, and then finds the definition
exported by libz, the reference is resolved



But when you try to link the program like:



the order of events is wrong in just the same way as with example 1.
At the point when the linker finds -lz, there are no references to anything
in the program: they are all in eg2.o, which has not yet been seen. So the
linker decides it has no use for libz. When it reaches eg2.o, adds it to the program,
and then has undefined reference to zlibVersion, the linkage sequence is finished;
that reference is unresolved, and the linkage fails.



Lastly, the pkg-config variation of example 2 has a now obvious explanation.
After shell-expansion:



becomes:



which is just example 2 again.



The linkage:



works just fine for you!



(Or: That linkage worked fine for you on, say, Fedora 23, but fails on Ubuntu 16.04)



That's because the distro on which the linkage works is one of the ones that
does not configure its GCC toolchain to link shared libraries as-needed.



Back in the day, it was normal for unix-like systems to link static and shared
libraries by different rules. Static libraries in a linkage sequence were linked
on the as-needed basis explained in example 1, but shared libraries were linked unconditionally.



This behaviour is economical at linktime because the linker doesn't have to ponder
whether a shared library is needed by the program: if it's a shared library,
link it. And most libraries in most linkages are shared libraries. But there are disadvantages too:-



It is uneconomical at runtime, because it can cause shared libraries to be
loaded along with a program even if doesn't need them.



The different linkage rules for static and shared libraries can be confusing
to inexpert programmers, who may not know whether -lfoo in their linkage
is going to resolve to /some/where/libfoo.a or to /some/where/libfoo.so,
and might not understand the difference between shared and static libraries
anyway.



This trade-off has led to the schismatic situation today. Some distros have
changed their GCC linkage rules for shared libraries so that the as-needed
principle applies for all libraries. Some distros have stuck with the old
way.



If I just do:



surely gcc has to compile eg1.c first, and then link the resulting
object file with libmy_lib.a. So how can it not know that object file
is needed when it's doing the linking?



Because compiling and linking with a single command does not change the
order of the linkage sequence.



When you run the command above, gcc figures out that you want compilation +
linkage. So behind the scenes, it generates a compilation command, and runs
it, then generates a linkage command, and runs it, as if you had run the
two commands:



So the linkage fails just as it does if you do run those two commands. The
only difference you notice in the failure is that gcc has generated a
temporary object file in the compile + link case, because you're not telling it
to use eg1.o. We see:



instead of:



The order in which interdependent linked libraries are specified is wrong



Putting interdependent libraries in the wrong order is just one way
in which you can get files that need definitions of things coming
later in the linkage than the files that provide the definitions. Putting libraries before the
object files that refer to them is another way of making the same mistake.



Linker errors can happen when a header file and its associated shared library (.lib file) go out of sync. Let me explain.



How do linkers work? The linker matches a function declaration (declared in the header) with its definition (in the shared library) by comparing their signatures. You can get a linker error if the linker doesn't find a function definition that matches perfectly.



Is it possible to still get a linker error even though the declaration and the definition seem to match? Yes! They might look the same in source code, but it really depends on what the compiler sees. Essentially you could end up with a situation like this:



Note how even though both the function declarations look identical in source code, but they are really different according to the compiler.



You might ask how one ends up in a situation like that? Include paths of course! If when compiling the shared library, the include path leads to header1.h and you end up using header2.h in your own program, you'll be left scratching your header wondering what happened (pun intended).



An example of how this can happen in the real world is explained below.



I have two projects: graphics.lib and main.exe. Both projects depend on common_math.h. Suppose the library exports the following function:



And then you go ahead and include the library in your own project.



Boom! You get a linker error and you have no idea why it's failing. The reason is that the common library uses different versions of the same include common_math.h (I have made it obvious here in the example by including a different path, but it might not always be so obvious. Maybe the include path is different in the compiler settings).



Note in this example, the linker would tell you it couldn't find draw(), when in reality you know it obviously is being exported by the library. You could spend hours scratching your head wondering what went wrong. The thing is, the linker sees a different signature because the parameter types are slightly different. In the example, vec3 is a different type in both projects as far as the compiler is concerned. This could happen because they come from two slightly different include files (maybe the include files come from two different versions of the library).



DUMPBIN is your friend, if you are using Visual Studio. I'm sure other compilers have other similar tools.



The process goes like this:



[1] By project I mean a set of source files that are linked together to produce either a library or an executable.



EDIT 1: Rewrote first section to be easier to understand. Please comment below to let me know if something else needs to be fixed. Thanks!



For people coming from C it might be a surprise that in C++ global constvariables have internal (or static) linkage. In C this was not the case, as all global variables are implicitly extern (i.e. when the static keyword is missing).



Example:



correct would be to use a header file and include it in file2.cpp and file1.cpp



Alternatively one could declare the const variable in file1.cpp with explicit extern




Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).


Would you like to answer one of these unanswered questions instead?

Popular posts from this blog

The Dalles, Oregon

眉山市

清晰法令