什么是未定义的参考/未解析的外部符号错误?常见原因是什么?如何解决/预防?


当前回答

常量变量声明/定义中缺少“extern”(仅限C++)

对于来自C语言的人来说,在C++中,全局常量变量具有内部(或静态)联系可能是一件令人惊讶的事情。在C中情况并非如此,因为所有全局变量都是隐式外部变量(即,当缺少静态关键字时)。

例子:

// file1.cpp
const int test = 5;    // in C++ same as "static const int test = 5"
int test2 = 5;

// file2.cpp
extern const int test;
extern int test2;

void foo()
{
 int x = test;   // linker error in C++ , no error in C
 int y = test2;  // no problem
}

正确的做法是使用头文件并将其包含在file2.cpp和file1.cpp中

extern const int test;
extern int test2;

或者,可以使用显式extern在file1.cpp中声明const变量

其他回答

Visual Studio NuGet包需要更新以获得新的工具集版本

我在尝试将libpng与Visual Studio 2013链接时遇到了这个问题。问题是,包文件只有Visual Studio 2010和2012的库。

正确的解决方案是希望开发人员发布更新的软件包,然后进行升级,但这对我来说是有效的,因为我在VS2013的一个额外设置中进行了黑客攻击,指向了VS2012库文件。

我通过找到packagename\build\native\packagename.targets并在该文件中编辑了包(在解决方案目录中的packages文件夹中),复制了所有v110部分。我在条件字段中将v110更改为v120,只是非常小心地将文件名路径全部保留为v110。这只是允许Visual Studio 2013链接到2012年的库,在本例中,它起了作用。

需要考虑的一些拼写错误:(我作为初学者经常遇到)

如果您使用的是类:请检查您是否没有在定义函数的cpp文件中的函数名之前忘记“classname::”。如果使用forward声明:请确保声明正确的类型。例如:如果要转发声明“结构”,请使用“结构”而不是“类”。

不同的架构

您可能会看到这样的消息:

library machine type 'x64' conflicts with target machine type 'X86'

在这种情况下,这意味着可用符号用于不同于您正在编译的体系结构。

在Visual Studio上,这是由于错误的“平台”,您需要选择正确的平台或安装正确版本的库。

在Linux上,这可能是由于错误的库文件夹(例如,使用lib而不是lib64)。

在MacOS上,可以选择在同一文件中传送两种体系结构。可能是链接希望两个版本都存在,但只有一个版本存在。也可能是库所在的lib/lib64文件夹错误。

链接的.lib文件与.dll关联

我也有同样的问题。假设我有项目MyProject和TestProject。我已经有效地将MyProject的lib文件链接到TestProject。然而,此lib文件是在构建MyProject的DLL时生成的。此外,我没有包含MyProject中所有方法的源代码,只包含对DLL入口点的访问。

为了解决这个问题,我将MyProject构建为LIB,并将TestProject链接到此.LIB文件(我将生成的.LIB文件复制粘贴到TestProject文件夹中)。然后我可以再次将MyProject构建为DLL。它正在编译,因为TestProject链接到的库确实包含MyProject中类中所有方法的代码。

指定相互依赖的链接库的顺序是错误的。

如果库相互依赖,则库的链接顺序也很重要。通常,如果库A依赖于库B,那么在链接器标志中,libA必须出现在libB之前。

例如:

// 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;
};

创建库:

$ 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

编译:

$ 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

再说一遍,顺序很重要!