Ошибка lnk2019 ссылка на неразрешенный внешний символ c

C++ Documentation. Contribute to MicrosoftDocs/cpp-docs development by creating an account on GitHub.
title description ms.date f1_keywords helpviewer_keywords no-loc

Linker Tools Error LNK2019

All about the Microsoft Visual Studio Linker error LNK2019 and how to diagnose and correct it in C and C++ code.

09/07/2022

LNK2019

nochkclr.obj

LNK2019

_check_commonlanguageruntime_version

main

WinMain

wmain

wWinMain

__cdecl

__stdcall

__fastcall

__vectorcall

extern

static

const

ARCH

AVX2

wchar_t

VERBOSE

EXPORTS

SYMBOLS

DUMPBIN

UNDNAME

unresolved external symbol ‘symbol‘ referenced in function ‘function

The compiled code for function makes a reference or call to symbol, but the linker can’t find the symbol definition in any of the libraries or object files.

This error message is followed by fatal error LNK1120. To fix error LNK1120, you must fix all LNK2001 and LNK2019 errors first.

Possible causes

There are many ways to get this error. All of them involve a reference to a function or variable that the linker couldn’t resolve, or find a definition for. The compiler can identify when a symbol isn’t declared, but it can’t tell when the symbol isn’t defined. It’s because the definition may be in a different source file or library. If a symbol is referred to but never defined, the linker generates an unresolved external symbol error.

Here are some common problems that cause LNK2019:

The source file that contains the definition of the symbol isn’t compiled

In Visual Studio, make sure the source file that defines the symbol gets compiled as part of your project. Check the intermediate build output directory for a matching .obj file. If the source file isn’t compiled, right-click on the file in Solution Explorer, and then choose Properties to check the properties of the file. The Configuration Properties > General page should show an Item Type of C/C++ Compiler. On the command line, make sure the source file that contains the definition is compiled.

The object file or library that contains the definition of the symbol isn’t linked

In Visual Studio, make sure the object file or library that contains the symbol definition is linked as part of your project. On the command line, make sure the list of files to link includes the object file or library.

The declaration of the symbol isn’t spelled the same as the definition of the symbol

Verify you use the correct spelling and capitalization in both the declaration and the definition, and wherever the symbol is used or called.

A function is used but the type or number of the parameters don’t match the function definition

The function declaration must match the definition. Make sure the function call matches the declaration, and that the declaration matches the definition. Code that invokes function templates must also have matching function template declarations that include the same template parameters as the definition. For an example of a template declaration mismatch, see sample LNK2019e.cpp in the Examples section.

A function or variable is declared but not defined

LNK2019 can occur when a declaration exists in a header file, but no matching definition is implemented. For member functions or static data members, the implementation must include the class scope selector. For an example, see Missing Function Body or Variable.

The calling convention is different between the function declaration and the function definition

Some calling conventions (__cdecl, __stdcall, __fastcall, and __vectorcall) are encoded as part of the decorated name. Make sure the calling convention is the same.

A symbol is defined in a C file, but declared without using extern "C" in a C++ file

A file that’s compiled as C creates decorated names for symbols that are different from the decorated names for the same symbols declared in a C++ file, unless you use an extern "C" modifier. Make sure the declaration matches the compilation linkage for each symbol. Similarly, if you define a symbol in a C++ file that will be used by a C program, use extern "C" in the definition.

A symbol is defined as static and then later referenced outside the file

In C++, unlike C, global constants have static linkage. To get around this limitation, you can include the const initializations in a header file and include that header in your .cpp files, or you can make the variable non-constant and use a constant reference to access it.

A static member of a class isn’t defined

A static class member must have a unique definition, or it will violate the one-definition rule. A static class member that can’t be defined inline must be defined in one source file by using its fully qualified name. If it isn’t defined at all, the linker generates LNK2019.

A build dependency is only defined as a project dependency in the solution

In earlier versions of Visual Studio, this level of dependency was sufficient. However, starting with Visual Studio 2010, Visual Studio requires a project-to-project reference. If your project doesn’t have a project-to-project reference, you may receive this linker error. Add a project-to-project reference to fix it.

An entry point isn’t defined

The application code must define an appropriate entry point: main or wmain for console applications, and WinMain or wWinMain for Windows applications. For more information, see main function and command-line arguments or WinMain function. To use a custom entry point, specify the /ENTRY (Entry-Point Symbol) linker option.

You build a console application by using settings for a Windows application

If the error message is similar to unresolved external symbol WinMain referenced in function function_name, link by using /SUBSYSTEM:CONSOLE instead of /SUBSYSTEM:WINDOWS. For more information about this setting, and for instructions on how to set this property in Visual Studio, see /SUBSYSTEM (Specify Subsystem).

You attempt to link 64-bit libraries to 32-bit code, or 32-bit libraries to 64-bit code

Libraries and object files linked to your code must be compiled for the same architecture as your code. Make sure the libraries your project references are compiled for the same architecture as your project. Make sure the /LIBPATH or Additional Library Directories property points to libraries built for the correct architecture.

You use different compiler options for function inlining in different source files

Using inlined functions defined in .cpp files and mixing function inlining compiler options in different source files can cause LNK2019. For more information, see Function Inlining Problems.

You use automatic variables outside their scope

Automatic (function scope) variables can only be used in the scope of that function. These variables can’t be declared extern and used in other source files. For an example, see Automatic (Function Scope) Variables.

You call intrinsic functions or pass argument types to intrinsic functions that aren’t supported on your target architecture

For example, if you use an AVX2 intrinsic, but don’t specify the /ARCH:AVX2 compiler option, the compiler assumes that the intrinsic is an external function. Instead of generating an inline instruction, the compiler generates a call to an external symbol with the same name as the intrinsic. When the linker tries to find the definition of this missing function, it generates LNK2019. Make sure you only use intrinsics and types supported by your target architecture.

You mix code that uses native wchar_t with code that doesn’t

C++ language conformance work that was done in Visual Studio 2005 made wchar_t a native type by default. If not all files have been compiled by using the same /Zc:wchar_t settings, type references may not resolve to compatible types. Make sure wchar_t types in all library and object files are compatible. Either update from a wchar_t typedef, or use consistent /Zc:wchar_t settings when you compile.

You get errors for *printf* and *scanf* functions when you link a legacy static library

A static library that was built using a version of Visual Studio before Visual Studio 2015 may cause LNK2019 errors when linked with the UCRT. The UCRT header files <stdio.h>, <conio.h>, and <wchar.h>now define many *printf* and *scanf* variations as inline functions. The inlined functions are implemented by a smaller set of common functions. Individual exports for the inlined functions aren’t available in the standard UCRT libraries, which only export the common functions. There are a couple of ways to resolve this issue. The method we recommend is to rebuild the legacy library with your current version of Visual Studio. Make sure the library code uses the standard headers for the definitions of the *printf* and *scanf* functions that caused the errors. Another option for a legacy library that you can’t rebuild is to add legacy_stdio_definitions.lib to the list of libraries you link. This library file provides symbols for the *printf* and *scanf* functions that are inlined in the UCRT headers. For more information, see the Libraries section in Overview of potential upgrade issues.

Third-party library issues and vcpkg

If you see this error when you’re trying to configure a third-party library as part of your build, consider using vcpkg. vcpkg is a C++ package manager that uses your existing Visual Studio tools to install and build the library. vcpkg supports a large and growing list of third-party libraries. It sets all the configuration properties and dependencies required for successful builds as part of your project.

Diagnosis tools

Sometimes it’s difficult to tell why the linker can’t find a particular symbol definition. Often the problem is that you haven’t included the code that contains the definition in your build. Or, build options have created different decorated names for external symbols. There are several tools and options that can help you diagnose LNK2019 errors.

  • The /VERBOSE linker option can help you determine which files the linker references. This option can help you verify whether the file that contains the definition of the symbol is included in your build.

  • The /EXPORTS and /SYMBOLS options of the DUMPBIN utility can help you discover which symbols are defined in your .dll and object or library files. Make sure the exported decorated names match the decorated names the linker searches for.

  • The UNDNAME utility can show you the equivalent undecorated external symbol for a decorated name.

Examples

Here are several examples of code that causes LNK2019 errors, together with information about how to fix the errors.

A symbol is declared but not defined

In this example, an external variable is declared but not defined:

// LNK2019.cpp
// Compile by using: cl /EHsc /W4 LNK2019.cpp
// LNK2019 expected
extern char B[100];   // B isn't available to the linker
int main() {
   B[0] = ' ';   // LNK2019
}

Here’s another example where a variable and function are declared as extern but no definition is provided:

// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
   i++;
   g();
}
int main() {}

Unless i and g are defined in one of the files included in the build, the linker generates LNK2019. You can fix the errors by including the source code file that contains the definitions as part of the compilation. Alternatively, you can pass .obj files or .lib files that contain the definitions to the linker.

A static data member is declared but not defined

LNK2019 can also occur when a static data member is declared but not defined. The following sample generates LNK2019, and shows how to fix it.

// LNK2019b.cpp
// Compile by using: cl /EHsc LNK2019b.cpp
// LNK2019 expected
struct C {
   static int s;
};

// Uncomment the following line to fix the error.
// int C::s;

int main() {
   C c;
   C::s = 1;
}

Declaration parameters don’t match the definition

Code that invokes function templates must have matching function template declarations. Declarations must include the same template parameters as the definition. The following sample generates LNK2019 on a user-defined operator, and shows how to fix it.

// LNK2019e.cpp
// compile by using: cl /EHsc LNK2019e.cpp
// LNK2019 expected
#include <iostream>
using namespace std;

template<class T> class
Test {
   // The operator<< declaration doesn't match the definition below:
   friend ostream& operator<<(ostream&, Test&);
   // To fix, replace the line above with the following:
   // template<typename T> friend ostream& operator<<(ostream&, Test<T>&);
};

template<typename T>
ostream& operator<<(ostream& os, Test<T>& tt) {
   return os;
}

int main() {
   Test<int> t;
   cout << "Test: " << t << endl;   // LNK2019 unresolved external
}

Inconsistent wchar_t type definitions

This sample creates a DLL that has an export that uses WCHAR, which resolves to wchar_t.

// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}

The next sample uses the DLL in the previous sample, and generates LNK2019 because the types unsigned short* and WCHAR* aren’t the same.

// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);

int main() {
   func(0);
}

To fix this error, change unsigned short to wchar_t or WCHAR, or compile LNK2019g.cpp by using /Zc:wchar_t-.

See also

For more information about possible causes and solutions for LNK2019, LNK2001, and LNK1120 errors, see the Stack Overflow question: What is an undefined reference/unresolved external symbol error and how do I fix it?.

Определение

Данная ошибка означает, что в процессе компоновки программы, компоновщик не смог найти определение некоторой сущности, на которую есть ссылка (попытка использования) в программе.

К таким сущностям может относиться, например, функция или переменная.


Причины и решения

Возможных причин появления ошибки может быть несколько и это зависит от того, что представляет из себя собираемый проект. Всё множество ситуаций можно разбить на две большие группы:


Используются сторонние библиотеки

  • Не указана необходимая (статическая) библиотека для компоновщика.

    Например, к проекту подключен только *.h файл с объявлениями, но отсутствует код реализации, обычно это *.lib или *.a файлы (в зависимости от используемой системы).
    Требуется явно подключить библиотеку к проекту.

  • Для Visual C++ это можно сделать добавлением следующей строки прямо в код:

    #pragma comment(lib, "libname.lib")
    
  • Для gcc/clang требуется указать файл через ключ -l (эль)

  • Для Qt в .pro файле нужно использовать переменную LIBS:

    LIBS += -L[путь_к_библиотеке] -l[имя_библиотеки]
    
  • Для системы сборки cmake есть target_link_libraries.

  • Библиотека указана, но необходимая сущность, например, класс или функция фактически не экспортируется из библиотеки. Под Windows это может возникать из-за отсуствия __declspec(dllexport) перед сущностью. Обычно это решается макросами. Данная ситуация чаще всего характерна именно для библиотек, находящихся в процессе разработки, и доступных для модификации самому разработчику, нежели для каких-то стабильных версий действительно внешних для проекта библиотек. После разрешения экспортирования библиотеку, конечно же, нужно пересобрать перед непосредственным использованием проблемной сущности.

  • Библиотека указана, но не совпадает разрядность библиотеки и компилируемого кода.

    В общем случае, разрядность собираемого проекта (приложения или библиотеки) должна совпадать с разрядностью используемой сторонней библиотеки. Обычно производители библиотек предоставляют возможность выбора 32 или 64 бит версию использовать. Если библиотека поставляется в исходных кодах и собирается отдельно от текущего проекта, нужно также выбрать правильную разрядность.

  • Библиотека указана, но она собрана для другой (не совместимой) ОС.

    Например при сборке проекта в Windows осуществляется попытка использовать бинарный файл, собранный для Linux. В данном случае нужно использовать файлы, подходящие для вашей ОС.

  • Библиотека указана, но она собрана другим компилятором, не совместимым с используемым.

    Объектные файлы, полученные путем сборки C++ кода разными компиляторами для одной и той же ОС могут быть бинарно несовместимы друг с другом. Требуется использовать совместимые (скорее всего и вовсе одинаковые) компиляторы.

  • Библиотека указана, и собрана тем же компилятором, что и основной проект, но используются разные версии Run-Time библиотек.

    Например, для Visual C++ возможна ситуация, когда библиотека собрана с ключом /MDd, а основной проект с /MTd. Требуется задать ключи так, чтобы использовались одинаковые версии Run-Time библиотек.


Сторонние библиотеки не используются

  • Просто отсутствует определение функции.

    void f(int); // всего лишь объявление. Нет `тела` функции
    int main(){  
        f(42);   // undefined reference to `f(int)'
    }  
    

    Требуется добавить определение функции f:

    void f(int) {
        // тело функции
    }
    

    Может быть ещё частный случай с ошибкой вида:

    undefined reference to `vtable for <имя_класса>`
    

    Такая ошибка возникает, если объявленная виртуальная функция класса, не являющаяся чистой (=0), не содержит реализации.

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

    Нужно такую реализацию добавить. Если это делается вне класса, надо не забыть указать имя проблемного класса, иначе это будет просто свободная функция, которая не устраняет указанную проблему:

    void C::f(int) { // виртуальная функция-член вне определения класса
        // тело функции  
    } 
    
    void f(int) { // свободная функция, не устраняющая проблему
        // тело функции 
    } 
    

    Аналогичная ситуация может возникать при использовании пространств имён, когда объявлении функции находится в пространстве имён:

    // В заголовочном файле
    namespace N {
        void f(int);
    };    
    

    а при реализации указать это пространство имён забыли:

    // В файле реализации
    void f(int) { // функция в глобальном пространстве имён, не устраняющая проблему
        // тело функции  
    }
    
    namespace N {
    void f(int) { // функция в нужном пространстве имён
        // тело функции  
    }
    } // конец пространства имён
    

    Стоит заметить, что C++ разрешает перегрузку функций (существование одноимённых функций, но с разным набором параметров), и в этом случае важно, чтобы сигнатуры функций при объявлении и определении совпадали. Например, вместо объявленной void f(int) была реализована другая:

    void f(const char*) { // const char* вместо int
        // тело функции     
    }
    

    При вызове f(42) будет ошибка:

    undefined reference to `f(int)'
    

    Наличие связки шаблонного класса и дружественной функции также может приводить к ошибке. Например:

    template <class T>
    struct C {
        friend void f(C<T>);   // объявляет *НЕ*шаблонную дружественную функцию
    };
    
    template <class T>         // определяет шаблонную функцию 
    void f(C<T>) { }
    
    int main() {
        C<int> c;
        f(c);                  // undefined reference to `f(C<int>)'
    }
    

    Чтобы объявить шаблонную дружественную функцию, требуется добавить указание шаблонности:

    template <class T>
    struct C {
        template <class V>     // добавили шаблонность для friend функции
        friend void f(C<T>);
    };
    

    Важно, что имя шаблонного параметра для дружественной функции должно отличаться от имени параметра шаблонного класса T, т.к. иначе будет ошибка о сокрытии имени. В частном случае имя класса можно вовсе не указывать, и оставить template <class>. Но это не всегда будет правильным решением, т.к. фактически могла потребоваться дружественная специализация шаблона функции, а не сама шаблонная функция. Подробнее об использовании дружественных функций в шаблонном классе можно ознакомиться здесь.

  • Отсутствует определение статической переменной класса.

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

    Нужно добавить определение (выделить память) переменной:

    int S::i;
    
  • Неправильная реализация шаблонного кода.

    Например, реализация шаблонного кода помещена в *.cpp файл, хотя она должна находиться полностью в подключаемом *.h файле. Это требуется по той причине, что компилятор обрабатывает каждый модуль независимо, и в момент инстанцирования шаблона (подстановки конкретного типа) код его реализации должен быть виден. При этом если возможные типы шаблона известны заранее, можно произвести инстанцирование сразу рядом с телом шаблона и не предоставлять его наружу в исходном коде заголовочного файла. Пример:

    // unit.h
    #pragma once
    
    template <class T>
    T f(T);                    // объявление шаблона без реализации
    
    // unit.cpp
    #include "unit.h"
    
    template <class T>
    T f(T t) { return t + t; } // реализация шаблона
    
    template
    int f<int>(int);           // явное инстанцирование для int
    
    template
    double f<double>(double);  // явное инстанцирование для double
    
    // main.cpp
    #include "unit.h"
    
    int main() { 
        f(2);   // ok int
        f(1.5); // ok double
        f('a'); // undefined reference to `char f<char>(char)'
    }
    
  • Файл с кодом не был скомпилирован.

    Например, в случае использования make-файла не было прописано правило построения файла, а в случае использования IDE типа Visual Studio *.cpp файл не добавлен в список файлов проекта.

  • Виртуальная функция в базовом классе не объявлена как = 0 (pure-virtual).

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

    При использовании иерархии классов функция в базовом классе, не имеющая реализации должна быть помечена как «чистая»:

    struct B {
        void virtual f() = 0;
    };
    
  • Имя не имеет внешнего связывания.

    Например, есть объявление функции f в модуле А и даже ее реализация в модуле B, но реализация помечена как static:

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

    Аналогичная ситуация может возникнуть при использовании безымянного пространства имен:

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

    Или даже при наличии inline у функции:

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

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

Example:

// A.hpp
class A
{
public:
  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 */ }

jave.web's user avatar

jave.web

13.2k11 gold badges89 silver badges117 bronze badges

answered Mar 29, 2012 at 15:29

Chris Morris's user avatar

Chris MorrisChris Morris

4,2964 gold badges23 silver badges28 bronze badges

6

Check you are including all the source files within your solution that you are referencing.

If you are not including the source file (and thus the implementation) for the class Field in your project it won’t be built and you will be unable to link during compilation.

Alternatively, perhaps you are using a static or dynamic library and have forgotten to tell the linker about the .libs?

answered Mar 29, 2012 at 15:15

Konrad's user avatar

2

It looks to be missing a library or include, you can try to figure out what class of your library that have getName, getType etc … and put that in the header file or using #include.

Also if these happen to be from an external library, make sure you reference to them on your project file. For example, if this class belongs to an abc.lib then in your Visual Studio

  1. Click on Project Properties.
  2. Go to Configuration Properties, C/C++,
    Generate, verify you point to the abc.lib location under Additional
    Include Directories. Under Linker, Input, make sure you have the
    abc.lib under Additional Dependencies.

hackjutsu's user avatar

hackjutsu

8,04412 gold badges45 silver badges84 bronze badges

answered Mar 29, 2012 at 15:20

Fylix's user avatar

FylixFylix

2,4674 gold badges41 silver badges70 bronze badges

0

I’ve just seen the problem I can’t call a function from main in .cpp file, correctly declared in .h file and defined in .c file. Encountered a linker error. Meanwhile I can call function from usual .c file. Possibly it depends on call convention. Solution was to add following preproc lines in every .h file:

#ifdef __cplusplus
extern "C"
{
#endif

and these in the end

#ifdef __cplusplus
}
#endif

answered Sep 14, 2015 at 13:40

Alexey257's user avatar

Alexey257Alexey257

1111 silver badge3 bronze badges

I had an error where my project was compiled as x64 project. and I’ve used a Library that was compiled as x86.

I’ve recompiled the library as x64 and it solved it.

answered Feb 6, 2017 at 13:55

Gal Bracha's user avatar

Gal BrachaGal Bracha

18.1k11 gold badges71 silver badges85 bronze badges

sometimes if a new header file is added, and this error starts coming due to that, you need to add library as well to get rid of unresolved external symbol.

for example:

#include WtsApi32.h

will need:

#pragma comment(lib, "Wtsapi32.lib") 

Santo's user avatar

Santo

1,6113 gold badges17 silver badges37 bronze badges

answered Jun 21, 2016 at 13:05

Shashank's user avatar

ShashankShashank

1161 silver badge5 bronze badges

I had the same link errors, but from a test project which was referencing another dll. Found out that after adding _declspec(dllexport) in front of each function which was specified in the error message, the link was working well.

answered Oct 8, 2016 at 12:41

meJustAndrew's user avatar

meJustAndrewmeJustAndrew

5,6677 gold badges53 silver badges71 bronze badges

1

Yet another possible problem (that I just scratched my head about for some time):

If you define your functions as inline, they—of course!—have to be defined in the header (or an inline file), not a cpp.
In my case, they were in an inline file, but only because they were a platform specific implementation, and a cpp included this corresponding inl file… instead of a header. Yeah, s**t happens.

I thought I’d leave this here, too, maybe someone else runs into the same issue and finds it here.

answered Oct 16, 2017 at 22:30

Johann Studanski's user avatar

1

This error can be caused by putting the function definitions for a template class in a separate .cpp file. For a template class, the member functions have to be declared in the header file. You can resolve the issue by defining the member functions inline or right after the class definition in the .h file.

For example, instead of putting the function definitions in a .cpp file like for other classes, you could define them inline like this:

template<typename T>
MyClassName {
  void someFunction() {
    // Do something
    ...
  }
  void anotherFunction() {
    // Do something else
    ...
  }
}

Or you could define them after the class definition but in the same file, like this:

template<typename T>
MyClassName {
  void someFunction();
  void anotherFunction();
}

void MyClassName::someFunction() {
  // Do something
  ...
}
void MyClassName::anotherFunction() {
  // Do something else
  ...
}

I just thought I’d share that since no one else seems to have mentioned template classes. This was the cause of the error in my case.

answered Aug 3, 2020 at 20:25

Joshua R C's user avatar

In addition to the excellent answer by Chris Morris above, I found a very interesting way you can receive this same fault if you are calling to a virtual method that hasn’t been set to pure but doesn’t its own implementation. It is the exact same reason (the compiler can’t find an implementation of the method and therefore crooks), but my IDE did not catch this fault in the least bit.

for example, the following code would get a compilation error with the same error message:

//code testing an interface
class test
{
   void myFunc(); 
}

//define an interface
class IamInterface
{
    virtual void myFunc();
}

//implementation of the interface
class IamConcreteImpl
{
    void myFunc()
    {
       1+1=2;
    }
}

However, changing IamInterface myFunc() to be a pure virtual method (a method that «must» be implemented, that than a virtual method which is a method the «can» be overridden) will eliminate the compilation error.

//define an interface
class IamInterface
{
    virtual void myFunc() = 0;
}

Hopes this helps the next StackOverFlow person stepping through code!

answered May 11, 2015 at 13:26

GMLewisII's user avatar

GMLewisIIGMLewisII

3661 silver badge7 bronze badges

I believe most of the points regarding the causes and remedies have been covered by all contributors in this thread. I just want to point out for my ‘unresolved external’ problem, it was caused by a datatype defined as macro that gets substituted differently than expected, which results in that incorrect type being supplied to the function in question, and since the function with type is never defined, it couldn’t have been resolved. In particular, under C/C++ -> Language, there is an attribute called ‘Treat WChar_t As Built in Type, which should have been defined as ‘No (/Zc:wchar_t-)’ but did not in my case.

answered Nov 17, 2015 at 23:24

Patrick Nguyen's user avatar

1

I just had a hard time with this. Everything was logically set up. I declared a constructor but didn’t define it

class SomeClass
{
   SomeClass();  // needs the SomeClass::SomeClass(){} function defined somewhere, even here
}

I almost banged my head on my keyboard when I forgot something so elementary.

answered Jan 18, 2015 at 6:25

Joe Plante's user avatar

Joe PlanteJoe Plante

6,2402 gold badges29 silver badges23 bronze badges

See Linker Tools Error LNK2019 at MSDN, it has a detailed list of common problems that cause LNK2019.

answered Jun 12, 2015 at 12:46

Alessandro Jacopson's user avatar

Make sure you decorate your header files with

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Bad things -including this- can happen if you don’t

answered Jun 24, 2015 at 23:00

Panouden's user avatar

1

I’m doing some C++ for the first time in a long time, and I’m getting this error when I forget to add the ClassName:: prefix for the function definition, since this is a little unique to C++. So remember to check for that too!

answered Feb 23, 2015 at 21:13

Matthew Hayes's user avatar

Matthew HayesMatthew Hayes

1231 gold badge1 silver badge7 bronze badges

POINTERS

I had this problem and solved it by using pointer. I see that this wasn’t your issue but I thought I’d mention it because I sure wish it had been here when I saw this an hour ago. My issue was about declaring a static member variable without defining it (the definition needed to come after some other set ups) and of course a pointer doesn’t need a definition. Equally elementary mistake :P

answered May 7, 2015 at 9:09

Rabel's user avatar

RabelRabel

291 bronze badge

1

One possible cause of this linker error can also be inline functions that are declared but not defined in a header file that is then included somewhere else. Inline functions have to be defined in every translation unit they are used in.

answered Jan 26, 2017 at 13:22

bweber's user avatar

bweberbweber

3,5502 gold badges30 silver badges57 bronze badges

Make sure that you are not trying to overload the insertion or extraction operators as inline functions. I had this problem and it only went away when i removed that keyword.

answered Nov 17, 2017 at 4:00

Beck's user avatar

BeckBeck

113 bronze badges

What had caused it in my case:

I had a huge file Foo.cpp without a Foo.h. Foo.cpp began like this:

// ... 100 LOC here ...
namespace NS {
// ... 100 more LOC here ...
static int var;

I removed the «static» keyword and added a Foo.h with this:

extern int var;

Do you see the mistake?

I totally missed that var was originally defined in a namespace, because the namespace declaration was buried in other code. The fix is to change the extern like this:

namespace NS {
     extern int var;
}

answered Mar 2, 2018 at 14:54

Stefan Monov's user avatar

Stefan MonovStefan Monov

11.1k10 gold badges59 silver badges115 bronze badges

In my case, I needed add the function name to the DEF file.

LIBRARY   DEMO
EXPORTS
   ExistingFunction   @1
   MyNewFunction      @2

answered Jan 18, 2021 at 15:01

Thomas Weller's user avatar

Thomas WellerThomas Weller

53.2k20 gold badges122 silver badges210 bronze badges

My issue was a sconscript did not have the cpp file defined in it. This can be very confusing because Visual Studio has the cpp file in the project but something else entirely is building.

answered Jan 21, 2016 at 0:03

ubershmekel's user avatar

ubershmekelubershmekel

11.4k8 gold badges71 silver badges85 bronze badges

My issue was: I had to do forward declaration of the class whose ctor was «unresolved external».

In the file where I got the error, I had to put something like this:

#include "ClassB" 

class ClassB; // this solved the problem

class ClassA{
    void foo(){
        ClassB* tmp = new ClassB();
        // ...
    }
};

Of course, my project is much more complicated and this is just a snippet example. Also when using namespaces, declare them as well.

Community's user avatar

answered May 27, 2016 at 16:24

vicrucann's user avatar

vicrucannvicrucann

1,6951 gold badge24 silver badges33 bronze badges

Just spent a couple of hours to find that the issue was my main file had extension .c instead of .cpp

:/

answered Jul 15, 2016 at 23:49

Madhur's user avatar

MadhurMadhur

2,0491 gold badge22 silver badges31 bronze badges

Yet another possibility to check, it was my problem this time.

I had added the function to the library, and included the library’s output folder in the search path.

But I also had a folder with an older version of the library listed before, so VS was using the old library, and of course not finding the new function.

answered Mar 13, 2017 at 8:27

Francesco Dondi's user avatar

A possible reason for the «Unresolved external symbol» error can be the function calling convention.

Make sure that all the source files are using same standard (.c or .cpp), or specify the calling convention.

Otherwise, if one file is a C file (source.c) and another file is a .cpp file, and they link to the same header, then the «unresolved external symbol» error will be thrown, because the function is first defined as a C cdecl function, but then C++ file using the same header will look for a C++ function.

To avoid the «Unresolved external symbol error», make sure that the function calling convention is kept the same among the files using it.

answered Mar 8, 2020 at 17:27

Flavio's user avatar

FlavioFlavio

4313 silver badges26 bronze badges

I came here looking for a possible explanation before taking a closer look at the lines preceding the linker error. It turned out to have been an additional executable for which the global declaration was missing!

answered May 22, 2020 at 14:52

Jerry Miller's user avatar

Jerry MillerJerry Miller

9231 gold badge8 silver badges11 bronze badges

I faced a similar issue and finally managed to solve it by adding __declspec(dllimport) to the declaration of the class:

// A.hpp
class __declspec(dllimport) A
{
   public: void myFunc();

   // Function declaration
};

Adrian Mole's user avatar

Adrian Mole

48.2k140 gold badges49 silver badges78 bronze badges

answered Jan 31, 2021 at 12:04

mohamad soltani nezamabadi's user avatar

In my case I had multiple namespaces in my header file without nesting (one after the other) however in my source file I had accidentally nested one of the namespaces inside another:

// myExample.h

#ifndef MYEXAMPLE_H
#define MYEXAMPLE_H

namespace A
{
  void aFunc();
}

namespace B
{
  void bFunc();
}
// myExample.cpp

#include "myExample.h"

namespace A
{
  void aFunc()
  {
    ...
  }

  namespace B   // whoops! I nested this inside namespace A when I didn't mean to.
  {
    void bFunc()
    {
      ...
    }
  }
}
// main.cpp

#include "myExample.h"

int main()
{
  myExample::B::bFunc();
  
  return 0;
}

When I used F12 to «Go to definition» on the function in Main, Visual Studio found the code in the source file even though it was declared in a deeper namespace by accident.

Debugging Technique

I spotted the issue when renaming the function while trying to debug the issue. The rename preview window showed an «External References» node with the function inside the source file clearly nested under another namespace by accident.

answered Jan 22, 2022 at 0:01

Zodman's user avatar

ZodmanZodman

3,0392 gold badges31 silver badges38 bronze badges

I had the same issue. Mine was working one day and then not the next day after I pulled the latest code.

The latest code did not include the project I was referencing in my library. So when I rebuilt my library, it deleted that .obj file, whoopsy…..

I reincluded the project I needed, built my library, then rebuilt my project that was failing and it worked fine.

Moral of the story, verify your .obj file is where you are referencing it before diving too deep into the rabit hole.

answered Aug 5, 2022 at 12:42

Patrick G's user avatar

I have had an issue with the same error within my project which I have managed to resolved.

The problem led me here but I found it to be a build file problem within visual studio itself.

If you cannot find anything wrong with your code and your doing all of the above I would recommend looking in the yourProject.vcxproj file and check that it is including your MyClass.cpp and source files as

SynthProject.vcxproj

<ItemGroup>
  <ClCompile Include="main.cpp" />
  <ClCompile Include="myClass.cpp" />
</ItemGroup>
  <ItemGroup>
  <ClInclude Include="myClass.h" />
</ItemGroup>

SynthProject.vcxproj.filters

<ItemGroup>
  <ClCompile Include="main.cpp">
    <Filter>Source Files</Filter>
  </ClCompile>
  <ClCompile Include="myClass.cpp">
    <Filter>Source Files</Filter>
  </ClCompile>
</ItemGroup>
<ItemGroup>
  <ClInclude Include="myClass.h">
    <Filter>Header Files</Filter>
  </ClInclude>
</ItemGroup>

and not as

SynthProject.vcxproj

<ItemGroup>
  <ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
  <ClInclude Include="myClass.h" />
  <ClInclude Include="myClass.cpp" />
</ItemGroup>

SynthProject.vcxproj.filters

<ItemGroup>
    <ClCompile Include="main.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  <ClCompile Include="myClass.cpp">
    <Filter>Source Files</Filter>
  </ClCompile>
</ItemGroup>
<ItemGroup>
  <ClInclude Include="myClass.h">
    <Filter>Header Files</Filter>
  </ClInclude>
  <ClInclude Include="myClass.cpp">
    <Filter>Source Files</Filter>
  </ClInclude>
</ItemGroup>

I have managed to do this manually but would recommend unloading and adding the file back into the project if you do not have, or not using git.

answered Oct 10, 2022 at 19:47

Dan R M's user avatar

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

Example:

// A.hpp
class A
{
public:
  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 */ }

jave.web's user avatar

jave.web

13.2k11 gold badges89 silver badges117 bronze badges

answered Mar 29, 2012 at 15:29

Chris Morris's user avatar

Chris MorrisChris Morris

4,2964 gold badges23 silver badges28 bronze badges

6

Check you are including all the source files within your solution that you are referencing.

If you are not including the source file (and thus the implementation) for the class Field in your project it won’t be built and you will be unable to link during compilation.

Alternatively, perhaps you are using a static or dynamic library and have forgotten to tell the linker about the .libs?

answered Mar 29, 2012 at 15:15

Konrad's user avatar

2

It looks to be missing a library or include, you can try to figure out what class of your library that have getName, getType etc … and put that in the header file or using #include.

Also if these happen to be from an external library, make sure you reference to them on your project file. For example, if this class belongs to an abc.lib then in your Visual Studio

  1. Click on Project Properties.
  2. Go to Configuration Properties, C/C++,
    Generate, verify you point to the abc.lib location under Additional
    Include Directories. Under Linker, Input, make sure you have the
    abc.lib under Additional Dependencies.

hackjutsu's user avatar

hackjutsu

8,04412 gold badges45 silver badges84 bronze badges

answered Mar 29, 2012 at 15:20

Fylix's user avatar

FylixFylix

2,4674 gold badges41 silver badges70 bronze badges

0

I’ve just seen the problem I can’t call a function from main in .cpp file, correctly declared in .h file and defined in .c file. Encountered a linker error. Meanwhile I can call function from usual .c file. Possibly it depends on call convention. Solution was to add following preproc lines in every .h file:

#ifdef __cplusplus
extern "C"
{
#endif

and these in the end

#ifdef __cplusplus
}
#endif

answered Sep 14, 2015 at 13:40

Alexey257's user avatar

Alexey257Alexey257

1111 silver badge3 bronze badges

I had an error where my project was compiled as x64 project. and I’ve used a Library that was compiled as x86.

I’ve recompiled the library as x64 and it solved it.

answered Feb 6, 2017 at 13:55

Gal Bracha's user avatar

Gal BrachaGal Bracha

18.1k11 gold badges71 silver badges85 bronze badges

sometimes if a new header file is added, and this error starts coming due to that, you need to add library as well to get rid of unresolved external symbol.

for example:

#include WtsApi32.h

will need:

#pragma comment(lib, "Wtsapi32.lib") 

Santo's user avatar

Santo

1,6113 gold badges17 silver badges37 bronze badges

answered Jun 21, 2016 at 13:05

Shashank's user avatar

ShashankShashank

1161 silver badge5 bronze badges

I had the same link errors, but from a test project which was referencing another dll. Found out that after adding _declspec(dllexport) in front of each function which was specified in the error message, the link was working well.

answered Oct 8, 2016 at 12:41

meJustAndrew's user avatar

meJustAndrewmeJustAndrew

5,6677 gold badges53 silver badges71 bronze badges

1

Yet another possible problem (that I just scratched my head about for some time):

If you define your functions as inline, they—of course!—have to be defined in the header (or an inline file), not a cpp.
In my case, they were in an inline file, but only because they were a platform specific implementation, and a cpp included this corresponding inl file… instead of a header. Yeah, s**t happens.

I thought I’d leave this here, too, maybe someone else runs into the same issue and finds it here.

answered Oct 16, 2017 at 22:30

Johann Studanski's user avatar

1

This error can be caused by putting the function definitions for a template class in a separate .cpp file. For a template class, the member functions have to be declared in the header file. You can resolve the issue by defining the member functions inline or right after the class definition in the .h file.

For example, instead of putting the function definitions in a .cpp file like for other classes, you could define them inline like this:

template<typename T>
MyClassName {
  void someFunction() {
    // Do something
    ...
  }
  void anotherFunction() {
    // Do something else
    ...
  }
}

Or you could define them after the class definition but in the same file, like this:

template<typename T>
MyClassName {
  void someFunction();
  void anotherFunction();
}

void MyClassName::someFunction() {
  // Do something
  ...
}
void MyClassName::anotherFunction() {
  // Do something else
  ...
}

I just thought I’d share that since no one else seems to have mentioned template classes. This was the cause of the error in my case.

answered Aug 3, 2020 at 20:25

Joshua R C's user avatar

In addition to the excellent answer by Chris Morris above, I found a very interesting way you can receive this same fault if you are calling to a virtual method that hasn’t been set to pure but doesn’t its own implementation. It is the exact same reason (the compiler can’t find an implementation of the method and therefore crooks), but my IDE did not catch this fault in the least bit.

for example, the following code would get a compilation error with the same error message:

//code testing an interface
class test
{
   void myFunc(); 
}

//define an interface
class IamInterface
{
    virtual void myFunc();
}

//implementation of the interface
class IamConcreteImpl
{
    void myFunc()
    {
       1+1=2;
    }
}

However, changing IamInterface myFunc() to be a pure virtual method (a method that «must» be implemented, that than a virtual method which is a method the «can» be overridden) will eliminate the compilation error.

//define an interface
class IamInterface
{
    virtual void myFunc() = 0;
}

Hopes this helps the next StackOverFlow person stepping through code!

answered May 11, 2015 at 13:26

GMLewisII's user avatar

GMLewisIIGMLewisII

3661 silver badge7 bronze badges

I believe most of the points regarding the causes and remedies have been covered by all contributors in this thread. I just want to point out for my ‘unresolved external’ problem, it was caused by a datatype defined as macro that gets substituted differently than expected, which results in that incorrect type being supplied to the function in question, and since the function with type is never defined, it couldn’t have been resolved. In particular, under C/C++ -> Language, there is an attribute called ‘Treat WChar_t As Built in Type, which should have been defined as ‘No (/Zc:wchar_t-)’ but did not in my case.

answered Nov 17, 2015 at 23:24

Patrick Nguyen's user avatar

1

I just had a hard time with this. Everything was logically set up. I declared a constructor but didn’t define it

class SomeClass
{
   SomeClass();  // needs the SomeClass::SomeClass(){} function defined somewhere, even here
}

I almost banged my head on my keyboard when I forgot something so elementary.

answered Jan 18, 2015 at 6:25

Joe Plante's user avatar

Joe PlanteJoe Plante

6,2402 gold badges29 silver badges23 bronze badges

See Linker Tools Error LNK2019 at MSDN, it has a detailed list of common problems that cause LNK2019.

answered Jun 12, 2015 at 12:46

Alessandro Jacopson's user avatar

Make sure you decorate your header files with

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Bad things -including this- can happen if you don’t

answered Jun 24, 2015 at 23:00

Panouden's user avatar

1

I’m doing some C++ for the first time in a long time, and I’m getting this error when I forget to add the ClassName:: prefix for the function definition, since this is a little unique to C++. So remember to check for that too!

answered Feb 23, 2015 at 21:13

Matthew Hayes's user avatar

Matthew HayesMatthew Hayes

1231 gold badge1 silver badge7 bronze badges

POINTERS

I had this problem and solved it by using pointer. I see that this wasn’t your issue but I thought I’d mention it because I sure wish it had been here when I saw this an hour ago. My issue was about declaring a static member variable without defining it (the definition needed to come after some other set ups) and of course a pointer doesn’t need a definition. Equally elementary mistake :P

answered May 7, 2015 at 9:09

Rabel's user avatar

RabelRabel

291 bronze badge

1

One possible cause of this linker error can also be inline functions that are declared but not defined in a header file that is then included somewhere else. Inline functions have to be defined in every translation unit they are used in.

answered Jan 26, 2017 at 13:22

bweber's user avatar

bweberbweber

3,5502 gold badges30 silver badges57 bronze badges

Make sure that you are not trying to overload the insertion or extraction operators as inline functions. I had this problem and it only went away when i removed that keyword.

answered Nov 17, 2017 at 4:00

Beck's user avatar

BeckBeck

113 bronze badges

What had caused it in my case:

I had a huge file Foo.cpp without a Foo.h. Foo.cpp began like this:

// ... 100 LOC here ...
namespace NS {
// ... 100 more LOC here ...
static int var;

I removed the «static» keyword and added a Foo.h with this:

extern int var;

Do you see the mistake?

I totally missed that var was originally defined in a namespace, because the namespace declaration was buried in other code. The fix is to change the extern like this:

namespace NS {
     extern int var;
}

answered Mar 2, 2018 at 14:54

Stefan Monov's user avatar

Stefan MonovStefan Monov

11.1k10 gold badges59 silver badges115 bronze badges

In my case, I needed add the function name to the DEF file.

LIBRARY   DEMO
EXPORTS
   ExistingFunction   @1
   MyNewFunction      @2

answered Jan 18, 2021 at 15:01

Thomas Weller's user avatar

Thomas WellerThomas Weller

53.2k20 gold badges122 silver badges210 bronze badges

My issue was a sconscript did not have the cpp file defined in it. This can be very confusing because Visual Studio has the cpp file in the project but something else entirely is building.

answered Jan 21, 2016 at 0:03

ubershmekel's user avatar

ubershmekelubershmekel

11.4k8 gold badges71 silver badges85 bronze badges

My issue was: I had to do forward declaration of the class whose ctor was «unresolved external».

In the file where I got the error, I had to put something like this:

#include "ClassB" 

class ClassB; // this solved the problem

class ClassA{
    void foo(){
        ClassB* tmp = new ClassB();
        // ...
    }
};

Of course, my project is much more complicated and this is just a snippet example. Also when using namespaces, declare them as well.

Community's user avatar

answered May 27, 2016 at 16:24

vicrucann's user avatar

vicrucannvicrucann

1,6951 gold badge24 silver badges33 bronze badges

Just spent a couple of hours to find that the issue was my main file had extension .c instead of .cpp

:/

answered Jul 15, 2016 at 23:49

Madhur's user avatar

MadhurMadhur

2,0491 gold badge22 silver badges31 bronze badges

Yet another possibility to check, it was my problem this time.

I had added the function to the library, and included the library’s output folder in the search path.

But I also had a folder with an older version of the library listed before, so VS was using the old library, and of course not finding the new function.

answered Mar 13, 2017 at 8:27

Francesco Dondi's user avatar

A possible reason for the «Unresolved external symbol» error can be the function calling convention.

Make sure that all the source files are using same standard (.c or .cpp), or specify the calling convention.

Otherwise, if one file is a C file (source.c) and another file is a .cpp file, and they link to the same header, then the «unresolved external symbol» error will be thrown, because the function is first defined as a C cdecl function, but then C++ file using the same header will look for a C++ function.

To avoid the «Unresolved external symbol error», make sure that the function calling convention is kept the same among the files using it.

answered Mar 8, 2020 at 17:27

Flavio's user avatar

FlavioFlavio

4313 silver badges26 bronze badges

I came here looking for a possible explanation before taking a closer look at the lines preceding the linker error. It turned out to have been an additional executable for which the global declaration was missing!

answered May 22, 2020 at 14:52

Jerry Miller's user avatar

Jerry MillerJerry Miller

9231 gold badge8 silver badges11 bronze badges

I faced a similar issue and finally managed to solve it by adding __declspec(dllimport) to the declaration of the class:

// A.hpp
class __declspec(dllimport) A
{
   public: void myFunc();

   // Function declaration
};

Adrian Mole's user avatar

Adrian Mole

48.2k140 gold badges49 silver badges78 bronze badges

answered Jan 31, 2021 at 12:04

mohamad soltani nezamabadi's user avatar

In my case I had multiple namespaces in my header file without nesting (one after the other) however in my source file I had accidentally nested one of the namespaces inside another:

// myExample.h

#ifndef MYEXAMPLE_H
#define MYEXAMPLE_H

namespace A
{
  void aFunc();
}

namespace B
{
  void bFunc();
}
// myExample.cpp

#include "myExample.h"

namespace A
{
  void aFunc()
  {
    ...
  }

  namespace B   // whoops! I nested this inside namespace A when I didn't mean to.
  {
    void bFunc()
    {
      ...
    }
  }
}
// main.cpp

#include "myExample.h"

int main()
{
  myExample::B::bFunc();
  
  return 0;
}

When I used F12 to «Go to definition» on the function in Main, Visual Studio found the code in the source file even though it was declared in a deeper namespace by accident.

Debugging Technique

I spotted the issue when renaming the function while trying to debug the issue. The rename preview window showed an «External References» node with the function inside the source file clearly nested under another namespace by accident.

answered Jan 22, 2022 at 0:01

Zodman's user avatar

ZodmanZodman

3,0392 gold badges31 silver badges38 bronze badges

I had the same issue. Mine was working one day and then not the next day after I pulled the latest code.

The latest code did not include the project I was referencing in my library. So when I rebuilt my library, it deleted that .obj file, whoopsy…..

I reincluded the project I needed, built my library, then rebuilt my project that was failing and it worked fine.

Moral of the story, verify your .obj file is where you are referencing it before diving too deep into the rabit hole.

answered Aug 5, 2022 at 12:42

Patrick G's user avatar

I have had an issue with the same error within my project which I have managed to resolved.

The problem led me here but I found it to be a build file problem within visual studio itself.

If you cannot find anything wrong with your code and your doing all of the above I would recommend looking in the yourProject.vcxproj file and check that it is including your MyClass.cpp and source files as

SynthProject.vcxproj

<ItemGroup>
  <ClCompile Include="main.cpp" />
  <ClCompile Include="myClass.cpp" />
</ItemGroup>
  <ItemGroup>
  <ClInclude Include="myClass.h" />
</ItemGroup>

SynthProject.vcxproj.filters

<ItemGroup>
  <ClCompile Include="main.cpp">
    <Filter>Source Files</Filter>
  </ClCompile>
  <ClCompile Include="myClass.cpp">
    <Filter>Source Files</Filter>
  </ClCompile>
</ItemGroup>
<ItemGroup>
  <ClInclude Include="myClass.h">
    <Filter>Header Files</Filter>
  </ClInclude>
</ItemGroup>

and not as

SynthProject.vcxproj

<ItemGroup>
  <ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
  <ClInclude Include="myClass.h" />
  <ClInclude Include="myClass.cpp" />
</ItemGroup>

SynthProject.vcxproj.filters

<ItemGroup>
    <ClCompile Include="main.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  <ClCompile Include="myClass.cpp">
    <Filter>Source Files</Filter>
  </ClCompile>
</ItemGroup>
<ItemGroup>
  <ClInclude Include="myClass.h">
    <Filter>Header Files</Filter>
  </ClInclude>
  <ClInclude Include="myClass.cpp">
    <Filter>Source Files</Filter>
  </ClInclude>
</ItemGroup>

I have managed to do this manually but would recommend unloading and adding the file back into the project if you do not have, or not using git.

answered Oct 10, 2022 at 19:47

Dan R M's user avatar

  • Remove From My Forums
  • Вопрос

  • Работаю в с++. (VS 2008)

    Встретилась ошибка «LNK2019: ссылка на неразрешенный внешний символ»

    Возникает при вызове функции  Diagnoz_Database()

    Diagnoz DataBase[37];
    
    int D_DataBase=0;
    void Diagnoz_Redakt(int &parametr, Diagnoz &Sure);
    
    void Diagnoz_Database()
    {
    	int i, i_while, i_special, p; char *Dolzhnost;
    	system("cls");
    	fflush(stdin);
    	do{printf("This is a special service menu for editing database diagnosesn");
    	printf("Choose operationn");
    	printf("1 - Create new (empty) database (will overwrite)n2 - Loadn3 - Edit an existing databasenESC - exitn");
    	i_while=_getch();
    switch(i_while)
    	{
    case '1': for(i=0;i<37;i++){DataBase[i].toFile(i);}
    		  D_DataBase=1;
    		  printf("Press any keyn");
    		  break;
    case '2': for(i=0;i<37;i++){DataBase[i].fromFile(i);}
    		  D_DataBase=1;
    		  printf("Press any keyn");
    		  break;
    if(D_DataBase==1) {case '3': printf("Choose dolzhnost'n"); Dolzhnost=chooseD(p); i_special = p; printf("%S", Dolzhnost); Diagnoz_Redakt(parametr, DataBase[parametr]);}
    	}
    	}while(i_while!=27);
    }
    void Diagnoz_Redakt(int &parametr, Diagnoz &Sure)
    {
    	int i;
    	printf("You sure? (Y/N)n");
    	do{ i=_getch();
    	}while((i!=27) & (i!=110) & (i!=121));
    		if(i==121) {caseMenu(Sure);}
    }
    
    

     Без вызова компилируется нормально. Изменения типа функции, параметров и операторов (switch на if’ы и т.п) ничего не дает. Новых файлов и библиотек после написания функций не подключал. С lib-файлами тоже, вроде бы, все в порядке.

    В чем может быть проблема?

    Заранее спасибо за ответы.

    • Изменено

      25 сентября 2011 г. 15:25

    • Изменен тип
      PashaPashModerator
      25 сентября 2011 г. 23:10

Ответы

  • Abolmasov Dmitry

    » нужно реализовать функцию void caseMenu(Diagnoz &def), которая просто описана в классе, как дружественная, но реализации ее нет.»

    Petalvik

    » Одной из причин возникновения LNK2019 является область видимости.»

    Вы правы.

    Не знаю, является ли это багом моей версии VS, но при наличии более 1000 строк кода между объявлением и реализацией функции возникает ошибка. Решил ее, разбив все большие файлы с кодом на несколько малых.

    Всем большое спасибо за помощь.

    • Помечено в качестве ответа
      Abolmasov Dmitry
      30 сентября 2011 г. 11:23

Содержание

  1. Ошибка средств компоновщика LNK2019
  2. Возможные причины
  3. Исходный файл, содержащий определение символа, не компилируется
  4. Файл объекта или библиотека, содержащие определение символа, не связана
  5. Объявление символа не совпадает с определением символа.
  6. Функция используется, но тип или число параметров не совпадают с определением функции.
  7. Функция или переменная объявлена, но не определена
  8. Соглашение о вызовах отличается между объявлением функции и определением функции.
  9. Символ определяется в файле C, но объявлен без использования extern «C» в файле C++.
  10. Символ определяется как static и позже ссылается за пределами файла.
  11. Член static класса не определен
  12. Зависимость сборки определяется только как зависимость проекта в решении
  13. Точка входа не определена
  14. Создание консольного приложения с помощью параметров для приложения Windows
  15. Попытка связать 64-разрядные библиотеки с 32-разрядным кодом или 32-разрядными библиотеками с 64-разрядным кодом
  16. Для встраивание функций в разные исходные файлы используются различные параметры компилятора.
  17. Автоматические переменные используются вне их области
  18. Вы вызываете встроенные функции или передаете типы аргументов в встроенные функции, которые не поддерживаются в целевой архитектуре.
  19. Вы смешиваете код, который использует машинный wchar_t код с кодом, который не используется
  20. При связывании устаревшей библиотеки static возникают ошибки *printf* и *scanf* функции.
  21. Проблемы со сторонними библиотеками и vcpkg
  22. Средства диагностики
  23. Примеры
  24. Символ объявлен, но не определен
  25. Элемент static данных объявлен, но не определен
  26. Параметры объявления не соответствуют определению
  27. Несогласованные wchar_t определения типов
  28. См. также раздел
  29. Name already in use
  30. cpp-docs / docs / error-messages / tool-errors / linker-tools-error-lnk2019.md

Ошибка средств компоновщика LNK2019

неразрешенный externсимвол al «symbol«, на который ссылается функция «function«

Скомпилированный код для функции создает ссылку или вызов символа, но компоновщик не может найти определение символа ни в одной из библиотек или файлов объектов.

За этим сообщением об ошибке следует неустранимая ошибка LNK1120. Чтобы устранить ошибку LNK1120, сначала необходимо исправить все ошибки LNK2001 и LNK2019.

Возможные причины

Существует множество способов получения этой ошибки. Все они включают ссылку на функцию или переменную, для которых компоновщик не может разрешить или найти определение. Компилятор может определить, когда символ не объявлен, но не может определить, когда символ не определен. Это связано с тем, что определение может находиться в другом исходном файле или библиотеке. Если символ ссылается, но никогда не определен, компоновщик создает неразрешенную externошибку символа al.

Ниже приведены некоторые распространенные проблемы, вызывающие ошибку LNK2019.

Исходный файл, содержащий определение символа, не компилируется

В Visual Studio убедитесь, что исходный файл, определяющий символ, компилируется как часть проекта. Проверьте выходной каталог промежуточной сборки на наличие соответствующего OBJ-файла. Если исходный файл не компилируется, щелкните его правой кнопкой мыши в Обозреватель решений и выберите пункт «Свойства«, чтобы проверить свойства файла. На странице«Общиесвойства> конфигурации» должен отображаться тип элементакомпилятора C/C++. В командной строке убедитесь, что исходный файл, содержащий определение, компилируется.

Файл объекта или библиотека, содержащие определение символа, не связана

В Visual Studio убедитесь, что файл объекта или библиотека, содержащие определение символа, связаны как часть проекта. В командной строке убедитесь, что список файлов для ссылки содержит файл объекта или библиотеку.

Объявление символа не совпадает с определением символа.

Убедитесь, что в объявлении и определении используются правильные орфографические и прописные буквы, а также везде, где используется или вызывается символ.

Функция используется, но тип или число параметров не совпадают с определением функции.

Объявление функции должно соответствовать определению. Убедитесь, что вызов функции соответствует объявлению и что объявление соответствует определению. Код, вызывающий шаблоны функций, также должен иметь соответствующие объявления шаблонов функций, которые включают те же параметры шаблона, что и определение. Пример несоответствия объявления шаблона см. в примере LNK2019e.cpp в разделе «Примеры».

Функция или переменная объявлена, но не определена

LNK2019 может возникать, если объявление существует в файле заголовка, но не реализовано соответствующее определение. Для функций-членов или static членов данных реализация должна включать селектор области класса. Пример см. в разделе Missing Function Body or Variable.

Соглашение о вызовах отличается между объявлением функции и определением функции.

Некоторые соглашения о вызовах ( __cdecl , __stdcall , __fastcall и __vectorcall ) кодируются как часть декорированного имени. Убедитесь, что соглашение о вызовах совпадает.

Символ определяется в файле C, но объявлен без использования extern «C» в файле C++.

Файл, скомпилированный как C, создает декорированные имена для символов, отличающихся от украшенных имен для тех же символов, объявленных в файле C++, если не используется extern «C» модификатор. Убедитесь, что объявление соответствует компоновке компиляции для каждого символа. Аналогично, если символ определяется в файле C++, который будет использоваться программой C, в определении следует использовать extern «C» .

Символ определяется как static и позже ссылается за пределами файла.

В C++ в отличие от C глобальные constмуравьи имеют static компоновку. Чтобы обойти это ограничение, можно включить const инициализации в файл заголовка и включить этот заголовок в CPP-файлыconst или сделать переменную неантой и использовать constссылку на муравей для доступа к ней.

Член static класса не определен

Член static класса должен иметь уникальное определение или нарушать правило одноопределенного определения. Член static класса, который не может быть определен как встроенный, должен быть определен в одном исходном файле с помощью полного имени. Если он не определен вообще, компоновщик создает LNK2019.

Зависимость сборки определяется только как зависимость проекта в решении

В более ранних версиях Visual Studio этот уровень зависимости был достаточным. Тем не менее, начиная с Visual Studio 2010, Visual Studio требует ссылки на проект в проект. Если у проекта нет ссылки на проект в проект, может появиться эта ошибка компоновщика. Чтобы устранить ошибку, добавьте ссылку одного проекта на другой.

Точка входа не определена

Код приложения должен определить соответствующую точку входа: main для wmain консольных приложений, а также WinMain wWinMain для приложений Windows. Дополнительные сведения см. в описании main аргументов WinMain или функций командной строки. Чтобы использовать пользовательскую точку входа, укажите параметр компоновщика (символ точки входа). /ENTRY

Создание консольного приложения с помощью параметров для приложения Windows

Если сообщение об ошибке похоже на неразрешенный externсимвол WinMain al, на который ссылается функцияfunction_name, ссылка используется /SUBSYSTEM:CONSOLE вместо /SUBSYSTEM:WINDOWS . Дополнительные сведения об этом параметре и инструкции по настройке этого свойства в Visual Studio см. в разделе /SUBSYSTEM (Указание подсистемы).

Попытка связать 64-разрядные библиотеки с 32-разрядным кодом или 32-разрядными библиотеками с 64-разрядным кодом

Библиотеки и файлы объектов, связанные с кодом, должны быть скомпилированы для той же архитектуры, что и код. Убедитесь, что библиотеки, на которые ссылается проект, компилируются для той же архитектуры, что и проект. Убедитесь, /LIBPATH что свойство или дополнительные каталоги библиотек указывают на библиотеки, созданные для правильной архитектуры.

Для встраивание функций в разные исходные файлы используются различные параметры компилятора.

Использование встроенных функций, определенных в CPP-файлах, и смешение в различных исходных файлах параметров компилятора для встраивания функций может привести к возникновению ошибки LNK2019. Для получения дополнительной информации см. Function Inlining Problems.

Автоматические переменные используются вне их области

Автоматические переменные (области видимости функции) могут использоваться только в области видимости данной функции. Эти переменные не могут объявляться extern и использоваться в других исходных файлах. Пример см. в разделе Automatic (Function Scope) Variables.

Вы вызываете встроенные функции или передаете типы аргументов в встроенные функции, которые не поддерживаются в целевой архитектуре.

Например, если вы используете встроенную AVX2 функцию, но не указываете /ARCH:AVX2 параметр компилятора, компилятор предполагает, что встроенная функция al extern. Вместо создания встроенной инструкции компилятор создает вызов externсимвола al с тем же именем, что и встроенная инструкция. Когда компоновщик пытается найти определение этой отсутствующей функции, он создает ошибку LNK2019. Убедитесь, что используются только встроенные и типы, поддерживаемые целевой архитектурой.

Вы смешиваете код, который использует машинный wchar_t код с кодом, который не используется

Работа по соответствию языкаМ C++, выполненная в Visual Studio 2005, по умолчанию сделала wchar_t собственный тип. Если не все файлы были скомпилированы с помощью одних и того же /Zc:wchar_t параметра, ссылки на типы могут не разрешаться в совместимые типы. Убедитесь, что wchar_t типы во всех библиотеках и файлах объектов совместимы. Обновление из wchar_t typedef или использование согласованных параметров /Zc:wchar_t при компиляции.

При связывании устаревшей библиотеки static возникают ошибки *printf* и *scanf* функции.

Библиотека static , созданная с помощью версии Visual Studio до Visual Studio 2015, может привести к ошибкам LNK2019 при связывании с UCRT. Файлы заголовков UCRT и теперь определяют многие *printf* варианты как *scanf* inline функции. Встроенные функции реализуются небольшим набором общих функций. Отдельные экспорты встроенных функций недоступны в стандартных библиотеках UCRT, которые экспортируют только общие функции. Существует несколько способов решения этой проблемы. Рекомендуется перестроить устаревшую библиотеку с текущей версией Visual Studio. Убедитесь, что код библиотеки использует стандартные заголовки для определений *printf* и *scanf* функций, вызвавших ошибки. Еще один вариант для устаревшей библиотеки, которую нельзя перестроить, — добавить legacy_stdio_definitions.lib в список библиотек, которые вы связываете. Этот файл библиотеки предоставляет символы и *printf* *scanf* функции, которые встраиваются в заголовки UCRT. Дополнительные сведения см. в разделе «Библиотеки » статьи «Общие сведения о потенциальных проблемах обновления».

Проблемы со сторонними библиотеками и vcpkg

Если эта ошибка возникает при попытке настроить стороннюю библиотеку в рамках сборки, рассмотрите возможность использования vcpkg. vcpkg — это диспетчер пакетов C++, который использует существующие инструменты Visual Studio для установки и сборки библиотеки. vcpkg поддерживает большой и растущий список сторонних библиотек. Он задает все свойства и зависимости конфигурации, необходимые для успешных сборок в рамках проекта.

Средства диагностики

Иногда трудно определить, почему компоновщик не может найти определенное определение символа. Часто проблема заключается в том, что вы не включили код, содержащий определение в сборке. Кроме того, варианты сборки создали разные декорированные имена для externсимволов al. Существует несколько средств и вариантов, которые помогут диагностировать ошибки LNK2019.

Параметр /VERBOSE компоновщика поможет определить файлы ссылок компоновщика. Этот параметр поможет проверить, включен ли файл, содержащий определение символа, в сборку.

Служебная /EXPORTS DUMPBIN программа позволяет /SYMBOLS определить, какие символы определены в файлах .dll и объектов или библиотек. Убедитесь, что экспортированные имена совпадают с декорированными именами, которые выполняет поиск компоновщика.

Служебная UNDNAME программа может показать эквивалентный неоцененный externсимвол al для украшенного имени.

Примеры

Ниже приведено несколько примеров кода, вызывающих ошибки LNK2019, а также сведения об устранении ошибок.

Символ объявлен, но не определен

В этом примере переменная al объявлена extern, но не определена:

Ниже приведен еще один пример объявления переменной и функции, но extern не предоставляется определение:

Если i и g не определены в одном из файлов, включенных в сборку, компоновщик создает LNK2019. Чтобы исправить ошибки, включите файл исходного кода, который содержит определения, в процесс компиляции. Кроме того, можно передать .obj файлы или .lib файлы, содержащие определения компоновщика.

Элемент static данных объявлен, но не определен

LNK2019 также может возникать, когда static член данных объявлен, но не определен. В следующем примере показано возникновение ошибки LNK2019 и приводятся сведения по ее устранению.

Параметры объявления не соответствуют определению

Код, вызывающий шаблоны функций, должен иметь соответствующие объявления шаблонов функций. Объявления должны содержать те же параметры шаблона, что и определение. В следующем примере показано возникновение ошибки LNK2019 для определяемого пользователем оператора и приводятся сведения по ее устранению.

Несогласованные wchar_t определения типов

В этом примере создается библиотека DLL с экспортом, который использует WCHAR , который разрешается wchar_t в .

Следующий пример использует библиотеку DLL в предыдущем примере и создает LNK2019, так как типы unsigned short* и WCHAR* не совпадают.

Чтобы устранить эту ошибку, измените unsigned short wchar_t WCHAR или скомпилируйте LNK2019g.cpp с помощью . /Zc:wchar_t-

См. также раздел

Дополнительные сведения о возможных причинах и решениях ошибок LNK2019, LNK2001 и LNK1120 см. в вопросе Stack Overflow: What is an undefined reference/unresolved external symbol error and how do I fix it?

Источник

Name already in use

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink

Copy raw contents

Copy raw contents

Linker Tools Error LNK2019

unresolved external symbol ‘symbol‘ referenced in function ‘function

The compiled code for function makes a reference or call to symbol, but the linker can’t find the symbol definition in any of the libraries or object files.

This error message is followed by fatal error LNK1120. To fix error LNK1120, you must fix all LNK2001 and LNK2019 errors first.

There are many ways to get this error. All of them involve a reference to a function or variable that the linker couldn’t resolve, or find a definition for. The compiler can identify when a symbol isn’t declared, but it can’t tell when the symbol isn’t defined. It’s because the definition may be in a different source file or library. If a symbol is referred to but never defined, the linker generates an unresolved external symbol error.

Here are some common problems that cause LNK2019:

The source file that contains the definition of the symbol isn’t compiled

In Visual Studio, make sure the source file that defines the symbol gets compiled as part of your project. Check the intermediate build output directory for a matching .obj file. If the source file isn’t compiled, right-click on the file in Solution Explorer, and then choose Properties to check the properties of the file. The Configuration Properties > General page should show an Item Type of C/C++ Compiler. On the command line, make sure the source file that contains the definition is compiled.

The object file or library that contains the definition of the symbol isn’t linked

In Visual Studio, make sure the object file or library that contains the symbol definition is linked as part of your project. On the command line, make sure the list of files to link includes the object file or library.

The declaration of the symbol isn’t spelled the same as the definition of the symbol

Verify you use the correct spelling and capitalization in both the declaration and the definition, and wherever the symbol is used or called.

A function is used but the type or number of the parameters don’t match the function definition

The function declaration must match the definition. Make sure the function call matches the declaration, and that the declaration matches the definition. Code that invokes function templates must also have matching function template declarations that include the same template parameters as the definition. For an example of a template declaration mismatch, see sample LNK2019e.cpp in the Examples section.

A function or variable is declared but not defined

LNK2019 can occur when a declaration exists in a header file, but no matching definition is implemented. For member functions or static data members, the implementation must include the class scope selector. For an example, see Missing Function Body or Variable.

The calling convention is different between the function declaration and the function definition

Some calling conventions ( __cdecl , __stdcall , __fastcall , and __vectorcall ) are encoded as part of the decorated name. Make sure the calling convention is the same.

A symbol is defined in a C file, but declared without using extern «C» in a C++ file

A file that’s compiled as C creates decorated names for symbols that are different from the decorated names for the same symbols declared in a C++ file, unless you use an extern «C» modifier. Make sure the declaration matches the compilation linkage for each symbol. Similarly, if you define a symbol in a C++ file that will be used by a C program, use extern «C» in the definition.

A symbol is defined as static and then later referenced outside the file

In C++, unlike C, global constants have static linkage. To get around this limitation, you can include the const initializations in a header file and include that header in your .cpp files, or you can make the variable non-constant and use a constant reference to access it.

A static member of a class isn’t defined

A static class member must have a unique definition, or it will violate the one-definition rule. A static class member that can’t be defined inline must be defined in one source file by using its fully qualified name. If it isn’t defined at all, the linker generates LNK2019.

A build dependency is only defined as a project dependency in the solution

In earlier versions of Visual Studio, this level of dependency was sufficient. However, starting with Visual Studio 2010, Visual Studio requires a project-to-project reference. If your project doesn’t have a project-to-project reference, you may receive this linker error. Add a project-to-project reference to fix it.

An entry point isn’t defined

The application code must define an appropriate entry point: main or wmain for console applications, and WinMain or wWinMain for Windows applications. For more information, see main function and command-line arguments or WinMain function. To use a custom entry point, specify the /ENTRY (Entry-Point Symbol) linker option.

You build a console application by using settings for a Windows application

If the error message is similar to unresolved external symbol WinMain referenced in function function_name, link by using /SUBSYSTEM:CONSOLE instead of /SUBSYSTEM:WINDOWS . For more information about this setting, and for instructions on how to set this property in Visual Studio, see /SUBSYSTEM (Specify Subsystem).

You attempt to link 64-bit libraries to 32-bit code, or 32-bit libraries to 64-bit code

Libraries and object files linked to your code must be compiled for the same architecture as your code. Make sure the libraries your project references are compiled for the same architecture as your project. Make sure the /LIBPATH or Additional Library Directories property points to libraries built for the correct architecture.

You use different compiler options for function inlining in different source files

Using inlined functions defined in .cpp files and mixing function inlining compiler options in different source files can cause LNK2019. For more information, see Function Inlining Problems.

You use automatic variables outside their scope

Automatic (function scope) variables can only be used in the scope of that function. These variables can’t be declared extern and used in other source files. For an example, see Automatic (Function Scope) Variables.

You call intrinsic functions or pass argument types to intrinsic functions that aren’t supported on your target architecture

For example, if you use an AVX2 intrinsic, but don’t specify the /ARCH:AVX2 compiler option, the compiler assumes that the intrinsic is an external function. Instead of generating an inline instruction, the compiler generates a call to an external symbol with the same name as the intrinsic. When the linker tries to find the definition of this missing function, it generates LNK2019. Make sure you only use intrinsics and types supported by your target architecture.

You mix code that uses native wchar_t with code that doesn’t

C++ language conformance work that was done in Visual Studio 2005 made wchar_t a native type by default. If not all files have been compiled by using the same /Zc:wchar_t settings, type references may not resolve to compatible types. Make sure wchar_t types in all library and object files are compatible. Either update from a wchar_t typedef, or use consistent /Zc:wchar_t settings when you compile.

You get errors for *printf* and *scanf* functions when you link a legacy static library

A static library that was built using a version of Visual Studio before Visual Studio 2015 may cause LNK2019 errors when linked with the UCRT. The UCRT header files , , and now define many *printf* and *scanf* variations as inline functions. The inlined functions are implemented by a smaller set of common functions. Individual exports for the inlined functions aren’t available in the standard UCRT libraries, which only export the common functions. There are a couple of ways to resolve this issue. The method we recommend is to rebuild the legacy library with your current version of Visual Studio. Make sure the library code uses the standard headers for the definitions of the *printf* and *scanf* functions that caused the errors. Another option for a legacy library that you can’t rebuild is to add legacy_stdio_definitions.lib to the list of libraries you link. This library file provides symbols for the *printf* and *scanf* functions that are inlined in the UCRT headers. For more information, see the Libraries section in Overview of potential upgrade issues.

Third-party library issues and vcpkg

If you see this error when you’re trying to configure a third-party library as part of your build, consider using vcpkg. vcpkg is a C++ package manager that uses your existing Visual Studio tools to install and build the library. vcpkg supports a large and growing list of third-party libraries. It sets all the configuration properties and dependencies required for successful builds as part of your project.

Sometimes it’s difficult to tell why the linker can’t find a particular symbol definition. Often the problem is that you haven’t included the code that contains the definition in your build. Or, build options have created different decorated names for external symbols. There are several tools and options that can help you diagnose LNK2019 errors.

The /VERBOSE linker option can help you determine which files the linker references. This option can help you verify whether the file that contains the definition of the symbol is included in your build.

The /EXPORTS and /SYMBOLS options of the DUMPBIN utility can help you discover which symbols are defined in your .dll and object or library files. Make sure the exported decorated names match the decorated names the linker searches for.

The UNDNAME utility can show you the equivalent undecorated external symbol for a decorated name.

Here are several examples of code that causes LNK2019 errors, together with information about how to fix the errors.

A symbol is declared but not defined

In this example, an external variable is declared but not defined:

Here’s another example where a variable and function are declared as extern but no definition is provided:

Unless i and g are defined in one of the files included in the build, the linker generates LNK2019. You can fix the errors by including the source code file that contains the definitions as part of the compilation. Alternatively, you can pass .obj files or .lib files that contain the definitions to the linker.

A static data member is declared but not defined

LNK2019 can also occur when a static data member is declared but not defined. The following sample generates LNK2019, and shows how to fix it.

Declaration parameters don’t match the definition

Code that invokes function templates must have matching function template declarations. Declarations must include the same template parameters as the definition. The following sample generates LNK2019 on a user-defined operator, and shows how to fix it.

Inconsistent wchar_t type definitions

This sample creates a DLL that has an export that uses WCHAR , which resolves to wchar_t .

The next sample uses the DLL in the previous sample, and generates LNK2019 because the types unsigned short* and WCHAR* aren’t the same.

To fix this error, change unsigned short to wchar_t or WCHAR , or compile LNK2019g.cpp by using /Zc:wchar_t- .

For more information about possible causes and solutions for LNK2019, LNK2001, and LNK1120 errors, see the Stack Overflow question: What is an undefined reference/unresolved external symbol error and how do I fix it? .

Источник

Your linkage consumes libraries before the object files that refer to them

  • You are trying to compile and link your program with the GCC toolchain.
  • Your linkage specifies all of the necessary libraries and library search paths
  • If libfoo depends on libbar, then your linkage correctly puts libfoo before libbar.
  • Your linkage fails with undefined reference to something errors.
  • But all the undefined somethings are declared in the header files you have
    #included and are in fact defined in the libraries that you are linking.

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

A minimal example involving a static library you built yourself

my_lib.c

#include "my_lib.h"
#include <stdio.h>

void hw(void)
{
    puts("Hello World");
}

my_lib.h

#ifndef MY_LIB_H
#define MT_LIB_H

extern void hw(void);

#endif

eg1.c

#include <my_lib.h>

int main()
{
    hw();
    return 0;
}

You build your static library:

$ gcc -c -o my_lib.o my_lib.c
$ ar rcs libmy_lib.a my_lib.o

You compile your program:

$ gcc -I. -c -o eg1.o eg1.c

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

$ gcc -o eg1 -L. -lmy_lib eg1.o 
eg1.o: In function `main':
eg1.c:(.text+0x5): undefined reference to `hw'
collect2: error: ld returned 1 exit status

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

$ gcc -o eg1 -I. -L. -lmy_lib eg1.c
/tmp/ccQk1tvs.o: In function `main':
eg1.c:(.text+0x5): undefined reference to `hw'
collect2: error: ld returned 1 exit status

A minimal example involving a shared system library, the compression library libz

eg2.c

#include <zlib.h>
#include <stdio.h>

int main()
{
    printf("%sn",zlibVersion());
    return 0;
}

Compile your program:

$ gcc -c -o eg2.o eg2.c

Try to link your program with libz and fail:

$ gcc -o eg2 -lz eg2.o 
eg2.o: In function `main':
eg2.c:(.text+0x5): undefined reference to `zlibVersion'
collect2: error: ld returned 1 exit status

Same if you compile and link in one go:

$ gcc -o eg2 -I. -lz eg2.c
/tmp/ccxCiGn7.o: In function `main':
eg2.c:(.text+0x5): undefined reference to `zlibVersion'
collect2: error: ld returned 1 exit status

And a variation on example 2 involving pkg-config:

$ gcc -o eg2 $(pkg-config --libs zlib) eg2.o 
eg2.o: In function `main':
eg2.c:(.text+0x5): undefined reference to `zlibVersion'

What are you doing wrong?

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:

$ gcc -o eg1 eg1.o -L. -lmy_lib

Success:

$ ./eg1 
Hello World

Link example 2 correctly:

$ gcc -o eg2 eg2.o -lz

Success:

$ ./eg2 
1.2.8

Link the example 2 pkg-config variation correctly:

$ gcc -o eg2 eg2.o $(pkg-config --libs zlib) 
$ ./eg2
1.2.8

The explanation

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:

$ gcc -o eg1 -L. -lmy_lib eg1.o

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:

gcc -o eg2 -lz eg2.o

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:

gcc -o eg2 $(pkg-config --libs zlib) eg2.o

becomes:

gcc -o eg2 -lz eg2.o

which is just example 2 again.

I can reproduce the problem in example 1, but not in example 2

The linkage:

gcc -o eg2 -lz eg2.o

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.

Why do I still get this problem even if I compile-and-link at the same time?

If I just do:

$ gcc -o eg1 -I. -L. -lmy_lib eg1.c

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:

$ gcc -I. -c -o eg1.o eg1.c
$ gcc -o eg1 -L. -lmy_lib eg1.o

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:

/tmp/ccQk1tvs.o: In function `main'

instead of:

eg1.o: In function `main':

See also

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.

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Ошибка lnk2019 visual studio
  • Ошибка ls 0018 gta 5 epic games
  • Ошибка lnk2001 неразрешенный внешний символ
  • Ошибка ls 0013 rocket league
  • Ошибка lnk1169 обнаружен многократно определенный символ один или более

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии