可能有多种原因:(如果你遇到了其他原因欢迎在评论区补充)
原因1:依赖库的编译环境与当前环境不同
比如你可能都是在Linux下用g++编译,但是库的linux版本与当前linux版本差异过大
- 库编译时的glibc版本为2.17
- 而当前项目编译环境的glibc版本为2.31
可以通过ldd --version
查看glibc版本。如果差别过大,那么在当前项目中使用其他环境编译的动态库中的函数,就可能导致undefined reference to …某个函数。
再比如,你都是在Windows下开发C++, 但库和当前使用库的项目分别使用了Visual Studio和mingw64 g++进行编译,同样有很大可能导致无法兼容。
解决方法自然是统一环境,要么在新环境中重新编译库,要么把当前环境调整为原来编译库时的环境。
原因2:项目源码中混合了C和C++源码
比如你现在是想写C++工程的,但是有的源码后缀为.c也就是C源码,那么编译不会出错,但是ld链接阶段会报错undefined reference to C源码中的函数。
解决方法是把C源码中的函数声明添加extern "C"
, 告诉编译器这是C函数,你在生成符号的时候不要对函数名称进行修饰。C++工程中用到C源码通常是这样搞的:
// 源文件 test.c
void testA()
{
}
void testB()
{
}
// 头文件 test.h
#ifndef __TEST_H__
#define __TEST_H__
#ifdef __cplusplus
extern "C" {
#endif
void testA();
void testB();
#ifdef __cplusplus
}
#endif
#endif // __TEST_H__
原因3:可能你设置了隐藏符号
例如,
- 你可能在cmake中设置了visibility=hidden, 默认隐藏所有符号,然后在C++代码中没有把其他二进制文件需要用到的符号给导出
__attribute__((visibility("default")))
; - 也可能是cmake中对编译的库设置了属性,通过version script把除了某几个符号之外的其他符号都隐藏了。
这里所说的符号,简单理解就是代码中的函数、类、以及全局变量等东西。
原因4:类的static变量未定义
原因:可能你在某个类中声明了一个static成员变量,但忘记在源文件中初始化了。