解决 undefined reference to 问题

31 篇文章 0 订阅

2020-12-14 14:07:53
最近又碰到一个问题,明明在cmake中添加了依赖的库,但库中某些函数能链接上,某些找不到符号,后面才发现是因为 cmake中没写库路径的情况下,链接了/usr/lib中的同名的依赖库,而/usr/lib中的库是早期版本,所有有些函数没有,自然找不到符号定义。两种解决方法:
1 删除/usr/lib中的老版本,避免混淆,同时cmake中加上 动态库路径
2 直接用新版本的依赖库替换/usr/lib中的库

2018年6月20日15:42:38
记录下 最近发现的一个问题
说有两个函数的定义找不到,初步用 nm 看了下, 导出了这两个函数的,
用 nm -D xxx.so 看了下, 发现函数签名中 参数 的类型不太一样, 一个是 c++0x ::basic_string之类的,
但找不到那个错误 报出的 是 std::string
原来 使用 xxx.so 的代码是用 C++11 编译的, 但 导出函数的xxx.so库是 C++0x编译的, 两个不统一,
导致 string 被修饰得不一样,所以发生 未定义错误!
使用 C++11 编译后就好了!

比如 boost库

./bootstrap.sh --with-toolset=gcc --prefix=/usr/local

./b2 -j12 toolset=gcc variant=release link=shared threading=multi address-model=64 cxxflags=-std=c++11 install

首先这篇文章总结得不错

https://blog.csdn.net/stpeace/article/details/73302833

然后依然会碰到问题,这时候就要看具体的函数签名了
Name Mangling in C++

参考
以下内容来自:
http://blog.51cto.com/hipercomer/855223

nm工具的 --demangle 选项 可以让函数名可读

name demangling
C++的name mangling技术一般使得函数变得面目全非,而很多情况下我们在查看这些符号的时候并不需要看到这些函数name mangling之后的效果,而是想看看是否定义了某个函数,或者是否引用了某个函数,这对于我们调试程序是非常有帮助的。
所以需要一种方法从name mangling之后的符号变换为name mangling之前的符号,这个过程称之为name demangling.事实上有很多工具提供这些功能,最常用的就是c++filt命令,c++filt命令接受一个name mangling之后的符号作为输入并输出demangling之后的符号。例如:

[lichao@sg01 name_mangling]$ c++filt _Z9test_funcRiPKcdSsf 
test_func(int&, char const*, double, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, float) 

一般更常用的方法为:

[lichao@sg01 name_mangling]$ nm func.o | c++filt 
 
0000000000000060 t global constructors keyed to _Z9test_funcRiPKcdSsf 
 
                 U _Unwind_Resume 
0000000000000022 t __static_initialization_and_destruction_0(int, int) 
 
0000000000000000 T test_func(int&, char const*, double, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, float) 
 
                 U std::allocator<char>::allocator() 
 
                 U std::allocator<char>::~allocator() 
 
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) 
 
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) 
 
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() 
 
                 U std::ios_base::Init::Init() 
                 U std::ios_base::Init::~Init() 
0000000000000000 b std::__ioinit 
 
                 U __cxa_atexit 
                 U __dso_handle 
                 U __gxx_personality_v0 
0000000000000076 t __tcf_0 
 
000000000000008e T main 
另外使用nm命令也可以demangle符号,使用选项-C即可,例如:
 
[lichao@sg01 name_mangling]$ nm -C func.o 
 
0000000000000060 t global constructors keyed to _Z9test_funcRiPKcdSsf 
 
                 U _Unwind_Resume 
0000000000000022 t __static_initialization_and_destruction_0(int, int) 
 
0000000000000000 T test_func(int&, char const*, double, std::string, float) 
 
                 U std::allocator<char>::allocator() 
 
                 U std::allocator<char>::~allocator() 
 
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) 
 
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) 
 
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() 
 
                 U std::ios_base::Init::Init() 
                 U std::ios_base::Init::~Init() 
0000000000000000 b std::__ioinit 
 
                 U __cxa_atexit 
                 U __dso_handle 
                 U __gxx_personality_v0 
0000000000000076 t __tcf_0 
 
000000000000008e T main 

又到了Last but not least important的时候了,还有一个特别重要的接口函数就是__cxa_demangle(),此函数的原型为:

namespace abi { 
extern "C" char* __cxa_demangle (const char* mangled_name, 
 
char* buf, 
size_t* n, 
int* status); 
} 

用于将mangled_name所指向的mangled进行demangle并将结果存放在buf中,n为buf的大小。status存放函数执行的结果,返回值为0表示执行成功。
下面是使用这个接口函数进行demangle的例子:

/* 
* Author: Chaos Lee 
 
* Description: Employ __cxa_demangle to demangle a mangling function name. 
 
* Date:2012/05/06 
 
* 
*/ 
#include<iostream> 
#include<cxxabi.h> 
using namespace std; 
 
using namespace abi; 
 
int main(int argc,char *argv[]) 
 
{ 
        const char * mangled_string = "_Z9test_funcRiPKcdSsf"; 
 
        char buffer[100]; 
        int status; 
        size_t n=100; 
        __cxa_demangle(mangled_string,buffer,&n,&status); 
 
        cout<<buffer<<endl; 
        cout<<status<<endl; 
        return 0; 
} 

测试结果:

[lichao@sg01 name_mangling]$ g++ cxa_demangle.cpp -o cxa_demangle

[lichao@sg01 name_mangling]$ ./cxa_demangle

test_func(int&, char const*, double, std::string, float)

0

### 回答1: "undefined reference to" 是一个编译错误,通常是由于缺少库文件或函数定义引起的。解决方法包括: 1. 确保库文件已经正确安装并且在编译时已经链接到程序中。 2. 检查函数定义是否正确,包括函数名、参数和返回类型等。 3. 如果使用了第三方库,确保已经正确包含头文件并链接库文件。 4. 如果使用了多个源文件,确保所有源文件都已经正确编译并链接到程序中。 5. 如果使用了模板或者宏定义,确保它们已经正确展开并且没有语法错误。 6. 如果使用了静态变量或者全局变量,确保它们已经正确定义并且没有重复定义。 总之,解决 "undefined reference to" 错误需要仔细检查代码和编译选项,找出问题所在并进行修复。 ### 回答2: undefined reference to(未定义的引用)是C++程序编译时最常见的错误之一。这种错误通常会出现在缺少头文件或者库文件的情况下。 解决undefined reference to错误的方法主要有以下几种: 1.头文件或者库文件没有包含。在编写程序代码时,使用到的函数、变量等需要在程序中被声明,否则编译器将会无法识别这些内容。因此,在写代码时,需要引入相应的头文件或者库文件。 2.库不匹配。当使用库文件时,需要检查库文件是否与系统环境相匹配。在Linux系统中,不同的库有不同的命名规则,因此需要确认库文件是否命名正确,是否放在正确的位置。 3.函数定义不完整。当出现未定义的引用时,可能是函数定义不完整导致的。检查代码中函数实现的完整性,确保没有遗漏任何必要元素。 4.变量调用不正确。当调用某个变量时,需要确认变量是否已经被正确的定义。如果没有被定义,就会出现undefined reference to错误。 总之,当出现undefined reference to错误时,尽管看起来比较恼人,但通常只需要检查上述几种错误原因,并对代码进行相应的修正,就能够充分解决问题。 ### 回答3: 当你编译程序时,可能会遇到“未定义引用”的错误,这通常是由于缺少某些库或文件的定义或链接问题引起的。最常见的解决方法是确保你包含了正确的库文件和头文件,以及正确地链接这些文件。以下是一些可能有用的解决方法: 1. 确保源代码文件中包含了你需要使用的所有头文件和库文件,并在编译命令中正确地链接这些文件。 2. 确保库文件被正确地安装和配置。如果你自己编译库文件,要确保编译和安装过程正确无误。 3. 检查你的编译器是否支持你需要使用的库文件。有时候,你的编译器版本或操作系统版本可能不支持某些库文件。 4. 检查是否有任何拼写错误或其他语法错误,并在需要的地方进行更正。 5. 如果你使用的是C++程序,则可能需要加上“extern C”语句来解决链接问题。这个语句可以将C++函数的名称转换为C函数的名称,以允许C++函数可以与C函数互相调用。 6. 最后,如果你不知道如何解决这个问题,可以在网络上搜寻相关的解决方案。许多社区和论坛都有关于处理“未定义引用”的问题的讨论,你可以从中找到有用的解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值