What Is an Undefined Reference/Unresolved External Symbol Error and How to Fix It

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

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].

  1. 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]
  2. 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]
  3. The source file is decomposed into preprocessing tokens (2.5) and sequences of white-space characters (including comments). [SNIP]
  4. Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. [SNIP]
  5. 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]
  6. Adjacent string literal tokens are concatenated.
  7. 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]
  8. Translated translation units and instantiation units are combined as follows: [SNIP]
  9. 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)

[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:

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()
x = 0;
Y y;
B b;

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

Common causes include:

  • 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

Unresolved external symbol in object files

This error often means that some function has a declaration, but not a definition.


// A.hpp
class A
void myFunc(); // Function declaration

// A.cpp

// Function definition
void A::myFunc()
// do stuff

In your case, the definition cannot be found. The issue could be that you are including a header file, which brings in some function declarations, but you either:

  1. do not define the functions in your cpp file (if you wrote this code yourself)
  2. do not include the lib/dll file that contains the definitions

A common mistake is that you define a function as a standalone and forget the class selector, e.g. A::, in your .cpp file:

Wrong: void myFunc() { /* do stuff */ }

Right: void A::myFunc() { /* do stuff */ }

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

There are many possible ways you can see an error like this. You may see it when trying to build your program (link error) or when running it (load error). Unfortunately, there's rarely a simple way to see which cause of your error you have.

This answer provides a summary of and links to the other answers to help you navigate. You may need to read all answers to solve your problem.

The most common cause of getting a link error like this is that you haven't correctly specified external dependencies or do not put all parts of your code together correctly.

When trying to run your program you may have a missing or incompatible runtime library.

If building fails and you have specified external dependencies, you may have a programming error which means that the compiler is looking for the wrong thing.

VS 2022: Unresolved external error when calling methods that are defined outside of the class definition

In C++ inline functions must have their body present in every translation unit from which they are called.

Removing inline doesn't change anything

Try to test it. I'm not the only one who proves that inline causes the lnk error. As
Sedenion says, it's a usage error.

I recommend reporting this wrong behavior to Developer Community and posting the link in this thread.

Related Topics

Leave a reply