- What is an undefined reference/unresolved external symbol error and how do I fix it?
- 39 Answers 39
- Class members:
- A pure virtual destructor needs an implementation.
- virtual methods must either be implemented or defined as pure.
- Non- virtual class members
- A common mistake is forgetting to qualify the name:
- static data members must be defined outside the class in a single translation unit:
- Failure to link against appropriate libraries/object files or compile implementation files
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?
@jave.web: While that does happen, the programmer usually notices that he has no this pointer and no access to class members. It’s quite rare to complete compilation and only fail during linking, when a non-static member function is missing its qualified-name.
@jave.web: This was exactly my problem. Thank you! I am new to cpp, but as far as I can tell, I was having the exact problem that Ben Voigt says was quite rare. I think your solution would make a great answer.
@Snaptastic see stackoverflow.com/a/12574407/673730 — A common mistake is forgetting to qualify the name 🙂
I would like to see minimal reproducible example as something we ask of most new users , honestly. I don’t mean anything by it, it is just — we can’t expect people to follow the rules we don’t inforce onto ourselves.
39 Answers 39
Compiling a C++ program takes place in several steps, as specified by 2.2 (credits to Keith Thompson for the reference):
- Physical source file characters are mapped, in an implementation-defined manner, to the basic source character set (introducing new-line characters for end-of-line indicators) if necessary. [SNIP]
- Each instance of a backslash character (\) immediately followed by a new-line character is deleted, splicing physical source lines to form logical source lines. [SNIP]
- The source file is decomposed into preprocessing tokens (2.5) and sequences of white-space characters (including comments). [SNIP]
- Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. [SNIP]
- Each source character set member in a character literal or a string literal, as well as each escape sequence and universal-character-name in a character literal or a non-raw string literal, is converted to the corresponding member of the execution character set; [SNIP]
- Adjacent string literal tokens are concatenated.
- White-space characters separating tokens are no longer significant. Each preprocessing token is converted into a token. (2.7). The resulting tokens are syntactically and semantically analyzed and translated as a translation unit. [SNIP]
- Translated translation units and instantiation units are combined as follows: [SNIP]
- All external entity references are resolved. Library components are linked to satisfy external references to entities not defined in the current translation. All such translator output is collected into a program image which contains information needed for execution in its execution environment. (emphasis mine)
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.
struct X < virtual void foo(); >; struct Y : X < void foo() <>>; struct A < virtual ~A() = 0; >; struct B: A < virtual ~B()<>>; extern int x; void foo(); int main()
will generate the following errors with GCC:
/home/AbiSfw/ccvvuHoX.o: In function `main': prog.cpp:(.text+0x10): undefined reference to `x' prog.cpp:(.text+0x19): undefined reference to `foo()' prog.cpp:(.text+0x2d): undefined reference to `A::~A()' /home/AbiSfw/ccvvuHoX.o: In function `B::~B()': prog.cpp:(.text._ZN1BD1Ev[B::~B()]+0xb): undefined reference to `A::~A()' /home/AbiSfw/ccvvuHoX.o: In function `B::~B()': prog.cpp:(.text._ZN1BD0Ev[B::~B()]+0x12): undefined reference to `A::~A()' /home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1Y[typeinfo for Y]+0x8): undefined reference to `typeinfo for X' /home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1B[typeinfo for B]+0x8): undefined reference to `typeinfo for A' collect2: ld returned 1 exit status
and similar errors with Microsoft Visual Studio:
1>test2.obj : error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ) 1>test2.obj : error LNK2001: unresolved external symbol "int x" (?x@@3HA) 1>test2.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall A::~A(void)" (??1A@@UAE@XZ) 1>test2.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall X::foo(void)" (?foo@X@@UAEXXZ) 1>. \test2.exe : fatal error LNK1120: 4 unresolved externals
- Failure to link against appropriate libraries/object files or compile implementation files
- Declared and undefined variable or function.
- Common issues with class-type members
- Template implementations not visible.
- Symbols were defined in a C program and used in C++ code.
- Incorrectly importing/exporting methods/classes across modules/dll. (MSVS specific)
- Circular library dependency
- undefined reference to `WinMain@16′
- Interdependent library order
- Multiple source files of the same name
- Mistyping or not including the .lib extension when using the #pragma (Microsoft Visual Studio)
- Problems with template friends
- Inconsistent UNICODE definitions
- Missing «extern» in const variable declarations/definitions (C++ only)
- Visual Studio Code not configured for a multiple file project
- Errors on Mac OS X when building a dylib, but a .so on other Unix-y systems is OK
Personally, I think the MS linker error messages are just as readable as the GCC errors. They also have the advantage of including both the mangled and unmangled names for the unresolved external. Having the mangled name can be helpful when you need to look at the libraries or object files directly to see what the problem might be (for example, a calling convention mismatch). Also, I’m not sure what version of MSVC produced the errors here, but newer versions include the name (both mangled and unmangled) of the function referring to the unresolved external symbol.
David Drysdale wrote a great article about how linkers work: Beginner’s Guide to Linkers. Given the topic of this question, I thought it might prove useful.
I just came across another possible reason for the unresolved symbol compiler error. A function was originally defined as inline inside a header, but I changed it to a declaration and defined it separately inside a source file. This failed with an unresolved symbol compiler error until I removed the inline keyword from both the declaration and definition.
Class members:
A pure virtual destructor needs an implementation.
Declaring a destructor pure still requires you to define it (unlike a regular function):
struct X < virtual ~X() = 0; >; struct Y : X < ~Y() <>>; int main() < Y y; >//X::~X()<> //uncomment this line for successful definition
This happens because base class destructors are called when the object is destroyed implicitly, so a definition is required.
virtual methods must either be implemented or defined as pure.
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:
struct X < virtual void foo(); >; struct Y : X < void foo() <>>; int main() < Y y; //linker error although there was no call to X::foo >
For this to work, declare X::foo() as pure:
Non- virtual class members
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:
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.
A common mistake is forgetting to qualify the name:
struct A < void foo(); >; void foo() <> int main()
static data members must be defined outside the class in a single translation unit:
struct X < static int x; >; int main() < int x = X::x; >//int X::x; //uncomment this line to define X::x
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.
Just thought you might want to stress that doing both is possible, and the dtor is not actually an exception. (it’s not obvious from your wording at first glance.)
Failure to link against appropriate libraries/object files or compile implementation files
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.
g++ -o test objectFile1.o objectFile2.o -lLibraryName
-l. must be to the right of any .o / .c / .cpp files.
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».