什么是未定义的引用 / 未解析的外部符号错误? 如何修复它?

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

Feel free to edit/add your own.

转载于:https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix

csdnceshi73
喵-见缝插针 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.
3 年多之前 回复
csdnceshi76
斗士狗 see stackoverflow.com/a/12574407/673730 - A common mistake is forgetting to qualify the name :)
接近 4 年之前 回复
csdnceshi51
旧行李 This was exactly my problem. Thank you! I am new to cpp, but as far as I can tell, I was having the exact problem that Ben Voigt says was quite rare. I think your solution would make a great answer.
接近 4 年之前 回复
csdnceshi77
狐狸.fox If this happens to you with a Qt signal, you most likely forgot the Q_OBJECT macro.
大约 5 年之前 回复
csdnceshi53
Lotus@ While that does happen, the programmer usually notices that he has no this pointer and no access to class members. It's quite rare to complete compilation and only fail during linking, when a non-static member function is missing its qualified-name.
5 年多之前 回复
csdnceshi80
胖鸭 Pretty common mistake is that you define a function as a standalone and forget the class selector (e.g. A::) in your .cpp file: You do this (wrong): void myFunc() { /* do stuff */ } Instead of this (right): void A::myFunc() { /* do stuff */ }
5 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 'feel free to add an answer' I preferred to add the relevant link (IMHO) your primary answer, if you'd like to permit.
6 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 I've been marking this question to be a possible dupe of this one. But after going through all of your (brilliant) answers, I can't see this case covered here. I'm aware it's specific about how an IDE sets up the project type and it's linkage dependencies. But that's a such frequently asked question I think it would be worth covered (maybe just with a link to another appropriate dupe) here. If it is already, and I just didn't spot it, forget about this request/comment.
6 年多之前 回复
csdnceshi59
ℙℕℤℝ One thing to consider adding is how to deal with "undefined vtable" and "undefined typeinfo" errors in particular (since they are less obvious than undefined functions or variables).
大约 7 年之前 回复

29个回答

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

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

  1. Physical source file characters are mapped, in an implementation-defined manner, to the basic source character set (introducing new-line characters for end-of-line indicators) if necessary. [SNIP]
  2. Each instance of a backslash character (\) immediately followed by a new-line character is deleted, splicing physical source lines to form logical source lines. [SNIP]
  3. The source file is decomposed into preprocessing tokens (2.5) and sequences of white-space characters (including comments). [SNIP]
  4. Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. [SNIP]
  5. Each source character set member in a character literal or a string literal, as well as each escape sequence and universal-character-name in a character literal or a non-raw string literal, is converted to the corresponding member of the execution character set; [SNIP]
  6. Adjacent string literal tokens are concatenated.
  7. White-space characters separating tokens are no longer significant. Each preprocessing token is converted into a token. (2.7). The resulting tokens are syntactically and semantically analyzed and translated as a translation unit. [SNIP]
  8. Translated translation units and instantiation units are combined as follows: [SNIP]
  9. All external entity references are resolved. Library components are linked to satisfy external references to entities not defined in the current translation. All such translator output is collected into a program image which contains information needed for execution in its execution environment. (emphasis mine)

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

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

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

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

Similar mechanisms exist for other compilers/ platforms.

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

The code:

struct X
{
   virtual void foo();
};
struct Y : X
{
   void foo() {}
};
struct A
{
   virtual ~A() = 0;
};
struct B: A
{
   virtual ~B(){}
};
extern int x;
void foo();
int main()
{
   x = 0;
   foo();
   Y y;
   B b;
}

will generate the following errors with GCC:

/home/AbiSfw/ccvvuHoX.o: In function `main':
prog.cpp:(.text+0x10): undefined reference to `x'
prog.cpp:(.text+0x19): undefined reference to `foo()'
prog.cpp:(.text+0x2d): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD1Ev[B::~B()]+0xb): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD0Ev[B::~B()]+0x12): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1Y[typeinfo for Y]+0x8): undefined reference to `typeinfo for X'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1B[typeinfo for B]+0x8): undefined reference to `typeinfo for A'
collect2: ld returned 1 exit status

and similar errors with Microsoft Visual Studio:

1>test2.obj : error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)
1>test2.obj : error LNK2001: unresolved external symbol "int x" (?x@@3HA)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall A::~A(void)" (??1A@@UAE@XZ)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall X::foo(void)" (?foo@X@@UAEXXZ)
1>...\test2.exe : fatal error LNK1120: 4 unresolved externals

Common causes include:

csdnceshi59
ℙℕℤℝ it would be nice if you add the correct, fixing the above errors
2 年多之前 回复
weixin_41568127
?yb? Use gcc? MinGW to be more precise.
接近 4 年之前 回复
csdnceshi78
程序go And how to define where is my case?! stackoverflow.com/questions/32915615/…
接近 5 年之前 回复
csdnceshi50
三生石@ David Drysdale wrote a great article about how linkers work: Beginner's Guide to Linkers. Given the topic of this question, I thought it might prove useful.
大约 5 年之前 回复
csdnceshi79
python小菜 Personally, I think the MS linker error messages are just as readable as the GCC errors. They also have the advantage of including both the mangled and unmangled names for the unresolved external. Having the mangled name can be helpful when you need to look at the libraries or object files directly to see what the problem might be (for example, a calling convention mismatch). Also, I'm not sure what version of MSVC produced the errors here, but newer versions include the name (both mangled and unmangled) of the function referring to the unresolved external symbol.
6 年多之前 回复
csdnceshi51
旧行李 If only. I think you can modify output using this, but I haven't tried it.
6 年多之前 回复
weixin_41568126
乱世@小熊 is there a way to get better VS linker errors? To get it look more like gcc ones, for example.
6 年多之前 回复

Class members:

A pure virtual destructor needs an implementation.

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

struct X
{
    virtual ~X() = 0;
};
struct Y : X
{
    ~Y() {}
};
int main()
{
    Y y;
}
//X::~X(){} //uncomment this line for successful definition

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

virtual methods must either be implemented or defined as pure.

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

struct X
{
    virtual void foo();
};
struct Y : X
{
   void foo() {}
};
int main()
{
   Y y; //linker error although there was no call to X::foo
}

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

struct X
{
    virtual void foo() = 0;
};

Non-virtual class members

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

struct A
{ 
    ~A();
};

The following would yield the error:

A a;      //destructor undefined

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

struct A
{ 
    ~A() {}
};

or outside:

A::~A() {}

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

All used member methods need to be defined if used.

A common mistake is forgetting to qualify the name:

struct A
{
   void foo();
};

void foo() {}

int main()
{
   A a;
   a.foo();
}

The definition should be

void A::foo() {}

static data members must be defined outside the class in a single translation unit:

struct X
{
    static int x;
};
int main()
{
    int x = X::x;
}
//int X::x; //uncomment this line to define X::x

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

csdnceshi76
斗士狗 Just thought you might want to stress that doing both is possible, and the dtor is not actually an exception. (it's not obvious from your wording at first glance.)
接近 6 年之前 回复
weixin_41568196
撒拉嘿哟木头 see "A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required" (10.3 Virtual functions) - unless this was changed in C++14
接近 6 年之前 回复
weixin_41568196
撒拉嘿哟木头 "need" vs. "should". Pedantically, non-pure virtual functions need be defined (although, as mentioned, some compilers won't complain until you call them, but some will). I don't think I said you can't define pure virtuals.
接近 6 年之前 回复
csdnceshi76
斗士狗 No need to define any non-virtual function you never use. Also, no need to define any virtual function, if you never construct an object of the class, nor call it from a derived class you actually instantiate. In addition, all pure virtual functions can be defined.
接近 6 年之前 回复
weixin_41568174
from.. Not sure this part - C++11 allows initialization inside the class for all static const data members is correct. [class.static.data]/3 says you need to mark the static data members constexpr if they're not of integral or enumeration type.
接近 6 年之前 回复
csdnceshi72
谁还没个明天 The last line of this answer is incorrect, an in-class declaration is never a definition. (Definitions aren't needed for static members that aren't odr-used, which is common for integral compile-time constants)
大约 6 年之前 回复

Declared but did not define a variable or function.

A typical variable declaration is

extern int x;

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

int x;

For example, the following would generate an error:

extern int x;
int main()
{
    x = 0;
}
//int x; // uncomment this line for successful definition

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

void foo(); // declaration only
int main()
{
   foo();
}
//void foo() {} //uncomment this line for successful definition

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

void foo(int& x);
int main()
{
   int x;
   foo(x);
}
void foo(const int& x) {} //different function, doesn't provide a definition
                          //for void foo(int& x)

Other examples of mismatches include

  • Function/variable declared in one namespace, defined in another.
  • Function/variable declared as class member, defined as global (or vice versa).
  • Function return type, parameter number and types, and calling convention do not all exactly agree.

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

weixin_41568184
叼花硬汉 In VS, cpp files matching those in header #includes not added to the source directory also falls under the category of missing definitions.
2 年多之前 回复
csdnceshi74
7*4 already covered by stackoverflow.com/a/12574420/673730
大约 6 年之前 回复
csdnceshi69
YaoRaoLov People do ask about unresolved externals due to misspelled names, so it's not entirely obvious. (Not sure what you're referring to about parameter names. Parameter names are not part of the type.)
大约 7 年之前 回复
csdnceshi74
7*4 I left out function name misspell as it's fairly obvious. As for parameter names - what?
大约 7 年之前 回复

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

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

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

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

csdnceshi51
旧行李 This problem isn't specific to a library, it affects all libraries using Visual Studio's package management system. I just happened to find the other question because we both had problems with libpng. I also had the same problem (with the same solution) for libxml2, libiconv and glew. That question is about a problem with Visual Studio's package management system, and my answer explains the reason and provides a workaround. Someone just saw "unresolved external" and assumed it was a standard linker problem when it is actually a package management problem.
5 年多之前 回复
csdnceshi62
csdnceshi62 That question already has an accepted answer. It's marked as duplicate because the general cause is listed above. What would happen if we had an answer here for every proble with a library that's not included?
5 年多之前 回复
csdnceshi51
旧行李 I did want to post here as that question was exactly this issue, but it was marked as a duplicate of this question so I couldn't answer it there. So I posted my answer here instead.
5 年多之前 回复
csdnceshi62
csdnceshi62 This seems overly-specific - perhaps a new thread would be a better place for this answer.
5 年多之前 回复

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

What's the meaning of compilation ?

  • Visual Studio search into file .vcxproj and start compiling each file which has the extension .cpp. Order of compilation is undefined.So you must not assume that the file main.cpp is compiled first
  • If .cpp files depends on additional .h files in order to find symbols that may or may not be defined in the file .cpp
  • If exists one .cpp file in which the compiler could not find one symbol, a compiler time error raises the message Symbol x could not be found
  • For each file with extension .cpp is generated an object file .o and also Visual Studio writes the output in a file named ProjectName.Cpp.Clean.txt which contains all object files that must be processed by the linker.

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

Steps In Linking a project

  • Parse all the object files and find the definition which was only declared in headers ( eg: The code of one method of a class as is mentioned in previous answers, or event the initialization of a static variable which is member inside a class)
  • If one symbol could not be found in object files he also is searched in Additional Libraries.For adding a new library to a project Configuration properties -> VC++ Directories -> Library Directories and here you specified additional folder for searching libraries and Configuration properties -> Linker -> Input for specifying the name of the library. -If the Linker could not find the symbol which you write in one .cpp he raises a linker time error which may sound like error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)

Observation

  1. Once the Linker find one symbol he doesn't search in other libraries for it
  2. The order of linking libraries does matter.
  3. If Linker finds an external symbol in one static library he includes the symbol in the output of the project.However, if the library is shared( dynamic ) he doesn't include the code ( symbols ) in output, but Run-Time crashes may occur

How To Solve this kind of error

Compiler Time Error :

  • Make sure you write your c++ project syntactical correct.

Linker Time Error

  • Define all your symbol which you declare in your header files
  • Use #pragma once for allowing compiler not to include one header if it was already included in the current .cpp which are compiled
  • Make sure that your external library doesn't contain symbols that may enter into conflict with other symbols you defined in your header files
  • When you use the template to make sure you include the definition of each template function in the header file for allowing the compiler to generate appropriate code for any instantiations.
csdnceshi52
妄徒之命 Yes.But the build/linking process is being done in g++/Visual Studio(compiler provided by Microsoft for VS )/Eclipse/Net Beans in the same way
接近 5 年之前 回复
csdnceshi55
~Onlooker The problem is not actually about IDE but about a answer for linking problems. Linking problems are not related to the IDE but to the compiler and build process.
接近 5 年之前 回复
csdnceshi52
妄徒之命 You're right . But every in every IDE process of compilation/linking is being done slightly differently.But the files are processed exactly the same ( even g++ do the same thing when it parse the flags.. )
接近 5 年之前 回复
csdnceshi55
~Onlooker Is not your answer is specific for visual studio? The question does not specify any IDE/compiler tools so it makes your answer useless for non-visual-studio part.
接近 5 年之前 回复

The order in which interdependent linked libraries are specified is wrong.

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

For example:

// B.h
#ifndef B_H
#define B_H

struct B {
    B(int);
    int x;
};

#endif

// B.cpp
#include "B.h"
B::B(int xx) : x(xx) {}

// A.h
#include "B.h"

struct A {
    A(int x);
    B b;
};

// A.cpp
#include "A.h"

A::A(int x) : b(x) {}

// main.cpp
#include "A.h"

int main() {
    A a(5);
    return 0;
};

Create the libraries:

$ g++ -c A.cpp
$ g++ -c B.cpp
$ ar rvs libA.a A.o 
ar: creating libA.a
a - A.o
$ ar rvs libB.a B.o 
ar: creating libB.a
a - B.o

Compile:

$ g++ main.cpp -L. -lB -lA
./libA.a(A.o): In function `A::A(int)':
A.cpp:(.text+0x1c): undefined reference to `B::B(int)'
collect2: error: ld returned 1 exit status
$ g++ main.cpp -L. -lA -lB
$ ./a.out

So to repeat again, the order DOES matter!

csdnceshi68
local-host -Wl,--start-group .....-Wl,--end-group solves this problem.
2 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 I curious fact is that in my case I had one object file that depends on a shared library. I had to modify the Makefile and put the library AFTER the object with gcc 4.8.4 on Debian. On Centos 6.5 with gcc 4.4 the Makefile worked with no problem.
接近 4 年之前 回复

Symbols were defined in a C program and used in C++ code.

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

void foo();
int main()
{
    foo();
}

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

extern "C" void foo();
int main()
{
    foo();
}

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

extern "C" void foo();

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

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

extern "C" {
    #include "cheader.h"
}
csdnceshi69
YaoRaoLov As in the above comment, the 'Creating Mixed-Language Headers' section here helped: oracle.com/technetwork/articles/servers-storage-dev/…
3 年多之前 回复
csdnceshi51
旧行李 Or conversely, If you develop a C library, a nice rule is to protect the header file(s) by surrounding all exported declarations with #ifdef __cplusplus [\n] extern"C" { [\n] #endif and #ifdef __cplusplus [\n] } [\n] #endif ([\n] being real carriage return but I can't write this properly in comment).
大约 5 年之前 回复

If all else fails, recompile.

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

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

csdnceshi53
Lotus@ I expanded on your answer and linked in in the main one. Thanks.
6 年多之前 回复
csdnceshi53
Lotus@ Correct - this happens when libraries have a cyclic dependency.
6 年多之前 回复

Incorrectly importing/exporting methods/classes across modules/dll (compiler specific).

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

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

#ifdef THIS_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP __declspec(dllimport)
#endif

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

DLLIMPEXP void foo();

expands to

__declspec(dllexport) void foo();

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

__declspec(dllimport) void foo();

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

You can similary import/export classes:

class DLLIMPEXP X
{
};
csdnceshi80
胖鸭 I haven't used .def files in ages. Feel free to add an answer or edit this one.
7 年多之前 回复
csdnceshi72
谁还没个明天 To be complete, this answer should mention GCC's visibility and Windows' .def files, as these also influence the symbol name and presence.
7 年多之前 回复

A bug in the compiler/IDE

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

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

  • Clean the project (some IDEs have an option to do this, you can also manually do it by deleting the object files)
  • Try start a new project, copying all source code from the original one.
csdnceshi70
笑故挽风 There are 21 answers on this question and therefore a significant amount of answers aren't going to be a "likely" solution. If you dismiss all the answers that are below your likeliness threshold then this page effectively becomes useless as most of the common cases are easily spotted anyway.
4 年多之前 回复
csdnceshi77
狐狸.fox Believing that your tools are broken is most likely going to steer you away from the true cause. It is just so much more likely that you made a mistake than a compiler caused your problem. Cleaning your solution or re-creating your build configuration may fix build errors, but that doesn't mean there is a bug in the compiler. The linked "turned out it was a bug" is not confirmed by Microsoft and is not reproducible.
4 年多之前 回复
共29条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐