Home c++ Unresolved external symbol reference (possible causes)

Unresolved external symbol reference (possible causes)

Author

Date

Category

When trying to build a program, an error message of one of the following types appears:

  • unresolved external symbol reference …
  • undefined symbol reference …
  • unresolved external symbol …
  • undefined reference to …
  • error LNK2019 …

What does this mean and how to fix this error?


Answer 1, authority 100%

Definition

This error means that during the process of linking the program, the linker could not find the definition of some entity to which there is a reference (attempt to use) in the program.

Such entities may include, for example, a function or a variable.


Reasons and solutions

There may be several possible reasons for the error, and it depends on what the project is being built. The whole set of situations can be divided into two large groups:


Third party libraries are used

  • Required (static) library for linker not specified.

    For example, only a * .h file with declarations is connected to the project, but there is no implementation code, usually * .lib or * .a files (depending on the system used).
    It is required to explicitly link the library to the project.

  • For Visual C++ , this can be done by adding the following line directly to the code:

    # pragma comment (lib, "libname.lib")
    
  • For gcc / clang , you need to specify the file using the -l (el)

    key

  • For Qt, the LIBS variable must be used in the .pro file:

    LIBS + = -L [library_path] -l [library_name]
    
  • For the cmake build system, there is target_link_libraries .

  • The library is specified, but the required entity, such as a class or function, is not actually exported from the library. On Windows this can happen due to the absence of __declspec (dllexport) before the entity. Usually this is solved by macros . This situation is most often typical for libraries that are in the development process and available for modification by the developer himself, rather than for some stable versions of libraries that are really external to the project. After allowing the export, the library must of course be rebuilt before using the problematic entity directly.

  • The library is specified, but the bitness of the library and the compiled code does not match.

    In general, the bitness of the project (application or library) being built must match the bitness of the third-party library being used. Typically, library vendors provide a choice of 32 or 64 bit version to use. If the library is supplied in source codes and is built separately from the current project, you must also select the correct bit depth.

  • The library is listed, but it was built for a different (not compatible) OS.

    For example, when building a project on Windows, an attempt is made to use a binary file compiled for Linux. In this case, you need to use the files suitable for your OS.

  • The library is listed, but it was built by a different compiler that is not compatible with the one being used.

    Object files obtained by building C++ code with different compilers for the same OS may be binary incompatible with each other. It is required to use compatible (most likely the same) compilers.

  • The library is listed and built with the same compiler as the main project, but different versions of the run-time libraries are used.

    For example, for Visual C++ a situation is possible when the library is built with the / MDd key, and the main project with / MTd . It is required to set the keys so that the same versions of the run-time libraries are used.


No third party libraries used

  • There is simply no function definition.

    void f (int); // just a declaration. No `body` function
    int main () {
      f (42); // undefined reference to `f (int) '
    }
    

    I want to add a function definition f :

    void f (int) {
      // function body
    }
    

    There may be another special case with an error like:

    undefined reference to `vtable for & lt; class_name & gt;`
    

    This error occurs if a declared virtual function of a class that is not pure (= 0 ) does not contain an implementation.

    class C {
      virtual void f (int);
    };
    

    You need to add such an implementation. If this is done outside the class, you must remember to specify the name of the problem class, otherwise it will be just a free function that does not fix the indicated problem:

    void C :: f (int) {// virtual member function outside the class definition
      // function body
    }
    void f (int) {// free function that does not fix the problem
      // function body
    }
    

    A similar situation can arise when using namespaces when the function declaration is in the namespace:

    // In the header file
    namespace N {
      void f (int);
    };
    

    and forgot to specify this namespace during implementation:

    // In the implementation file
    void f (int) {// function in the global namespace that does not fix the problem
      // function body
    }
    namespace N {
    void f (int) {// function in the desired namespace
      // function body
    }
    } // end of namespace
    

    It is worth noting that C++ allows function overloading (the existence of functions of the same name, but with a different set of parameters), and in this case it is important that the signatures of the functions coincide when declaring and defining them. For example, instead of the declared void f (int) , another was implemented:

    void f (const char *) {// const char * instead of int
      // function body
    }
    

    When calling f (42) , there will be an error:

    undefined reference to `f (int) '
    

    The presence of a bunch of a template class and a friendly function can also lead to an error. For example:

    template & lt; class T & gt;
    struct C {
      friend void f (C & lt; T & gt;); // declares * NOT * a templated friendly function
    };
    template & lt; class T & gt; // defines a templated function
    void f (C & lt; T & gt;) {}
    int main () {
      C & lt; int & gt; c;
      f (c); // undefined reference to `f (C & lt; int & gt;) '
    }
    

    To declare a templated friendly function, you need to add a template hint:

    template & lt; class T & gt;
    struct C {
      template & lt; class V & gt; // added boilerplate for friend function
      friend void f (C & lt; T & gt;);
    };
    

    It is important that the name of the template parameter for the friendly function must be different from the name of the parameter of the template class T , since otherwise, there will be an error about hiding the name. In a special case, the class name can be omitted at all, and you can leave template & lt; class & gt; . But this will not always be the right decision, because in fact, the friendly specialization of the function template might be required, not the template function itself. For more information on using friendly functions in a template class, see here .

  • Missing static class variable definition.

    struct S {
      static int i;
    };
    int main () {
      S s;
      s.i = 42; // undefined reference to `S :: i '
    }
    

    You need to add a definition (allocate memory) to the variable:

    int S :: i;
    
  • Incorrect implementation of boilerplate code.

    For example, the implementation of the boilerplate code is placed in the * .cpp file, although it must be located entirely in the include * .h file. This is required because the compiler processes each module independently, and at the moment of instantiating a template (substitution of a specific type), its implementation code must be visible. Moreover, if the possible types of the template are known in advance, you can instantiate right next to the body of the template and not expose it outside in the source code of the header file. Example:

    // unit.h
    #pragma once
    template & lt; class T & gt;
    T f (T); // template declaration without implementation
    
    // unit.cpp
    #include "unit.h"
    template & lt; class T & gt;
    T f (T t) {return t + t; } // implementation of the template
    template
    int f & lt; int & gt; (int); // explicit instantiation for int
    template
    double f & lt; double & gt; (double); // explicit instantiation for double
    
    // main.cpp
    #include "unit.h"
    int main () {
      f (2); // ok int
      f (1.5); // ok double
      f ('a'); // undefined reference to `char f & lt; char & gt; (char) '
    }
    
  • The code file was not compiled.

    For example, if a makefile was used, the file building rule was not written, and if an IDE of the Visual Studio type * .cpp was used, the file was not added to the list of project files.

  • The virtual function in the base class is not declared as = 0 (pure-virtual).

    struct B {
      void virtual f ();
    };
    struct D: B {
      void f () {}
    };
    int main () {
      D d;
    }
    

    When using a class hierarchy, a function in a base class that does not have an implementation should be marked as “clean”:

    struct B {
      void virtual f () = 0;
    };
    
  • The name has no external binding.

    For example, there is a declaration of the f function in the A module and even its implementation in the B module, but the implementation is marked as static :

    // A.cpp
    void f ();
    int main () {
      f (); // undefined reference to `f () '
    }
    // B.cpp
    static void f () {}
    

    A similar situation can arise when using an unnamed namespace:

    // B.cpp
    namespace {
      void f () {}
    }
    

    Or even if the function has inline :

    // B.cpp
    inline void f () {}
    

Answer 2, authority 21%

(In addition to the already existing answer)

  • When using Visual Studio or other compilers for the Windows platform, the execution of a project of type Windows Desktop Application starts with the WinMain function, and execution of a project of type Windows Console Application starts with the main function.

    If your program is written in plain C or C++, that is, it contains the standard classical function main , and you created your project by mistake with the type Windows Desktop Application , then upon linking you will receive a message stating that the WinMain function was not found by the linker.

    Conversely, if you created a project of type Windows Console Application , but instead of the main function, you defined the WinMain function in it, then when linking you get a message that the main function was not found by the linker.


Answer 3, authority 3%

Addendum to αλεχολυτ’s answer – as it turned out, some people manage to declare a purely virtual destructor:

class Base {
  ...
  virtual ~ Base () = 0;

and such tricks are not allowed, since the destructor of the base class is always called (except in the case of creating an object via new without a corresponding delete ). The result is the same undefined reference error.

Programmers, Start Your Engines!

Why spend time searching for the correct question and then entering your answer when you can find it in a second? That's what CompuTicket is all about! Here you'll find thousands of questions and answers from hundreds of computer languages.

Recent questions