什么是未定义的参考/未解析的外部符号错误?常见原因是什么?如何解决/预防?
当前回答
符号是在C程序中定义的,并在C++代码中使用。
函数(或变量)void foo()是在C程序中定义的,您尝试在C++程序中使用它:
void foo();
int main()
{
foo();
}
C++链接器希望名称被损坏,因此必须将函数声明为:
extern "C" void foo();
int main()
{
foo();
}
等效地,函数(或变量)void foo()不是在C程序中定义的,而是在C++中定义的但具有C链接:
extern "C" void foo();
并且尝试在C++链接的C++程序中使用它。
如果整个库包含在头文件中(并且编译为C代码);包括以下内容:;
extern "C" {
#include "cheader.h"
}
其他回答
跨模块.dll(编译器特定)错误地导入/导出方法/类。
MSVS要求您使用__declspec(dllexport)和__declsspec(dllimport)指定要导出和导入的符号。
这种双重功能通常通过使用宏来实现:
#ifdef THIS_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP __declspec(dllimport)
#endif
宏THIS_MODULE只能在导出函数的模块中定义。这样,声明:
DLLIMPEXP void foo();
扩展到
__declspec(dllexport) void foo();
并且告诉编译器导出函数,因为当前模块包含其定义。当将声明包含在不同的模块中时,它将扩展到
__declspec(dllimport) void foo();
并且告诉编译器,该定义位于链接到的一个库中(另请参见1)。
您可以使用类似的导入/导出类:
class DLLIMPEXP X
{
};
此外,如果您正在使用第三方库,请确保您拥有正确的32/64位二进制文件
使用带有代码运行程序扩展名和多个.c或.cpp文件的Visual Studio代码
所提供的Code Runner仅适用于具有单个源文件的编译程序。它不是为与多个源文件一起使用而设计的。您应该使用不同的扩展名,例如C/C++Makefile Project扩展名或CMake Tools扩展名,或者修复CodeRunner扩展名以处理多个文件,或者手动编辑.json配置文件。
指定相互依赖的链接库的顺序是错误的。
如果库相互依赖,则库的链接顺序也很重要。通常,如果库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
再说一遍,顺序很重要!
在我的例子中,语法是正确的,但当一个类调用同一DLL中的第二个类时,我出现了错误。第二个类的CPP文件在visual studio中具有错误的财产->项类型,在我的例子中,它被设置为C/C++头,而不是正确的C/C++编译器,因此编译器在构建CPP文件时没有编译它,并导致错误LNK2019
下面是一个示例,假设语法正确,您应该通过更改财产中的项类型来获得错误
//class A header file
class ClassB; // FORWARD DECLERATION
class ClassA
{
public:
ClassB* bObj;
ClassA(HINSTANCE hDLL) ;
// member functions
}
--------------------------------
//class A cpp file
ClassA::ClassA(HINSTANCE hDLL)
{
bObj = new ClassB();// LNK2019 occures here
bObj ->somefunction();// LNK2019 occures here
}
/*************************/
//classB Header file
struct mystruct{}
class ClassB{
public:
ClassB();
mystruct somefunction();
}
------------------------------
//classB cpp file
/* This is the file with the wrong property item type in visual studio --C/C++ Header-*/
ClassB::somefunction(){}
ClassB::ClassB(){}