5 解析未定义的符号(下)
来源:互联网 发布:e5 v3cpu 淘宝店推荐 编辑:程序博客网 时间:2024/05/16 10:08
——《软件调试实战》
C++的命名空间、类、模板或函数重载等特征使得编译和链接更为复杂,这使得符号的不匹配更有可能引发链接问题。甚至利用C和C++编译器编译相同的C源代码也会得到不同的符号。
1 符号的反改编(demangle)
为观察经过名称改编的符号,可以对这些符号进行反改编。有两种反改编方法:一是使用实用程序(analysis utility),它们可以在改编和反改编之间切换;二是使用过滤器,如c++filt。通过选项-C或–demingle可以调用实际的用户级别的符号名称。
2 连接C和C++代码
仅使用C编译器驱动程序并不能保证源代码实际上被编译为C代码,编译器驱动程序可能根据文件扩展名来决定生成C或C++风格的符号。例如,如果用gcc编译 .c 文件,则此文件被编译为C代码,而扩展名为 .cc, .cpp, .cxx 的文件则被编译为C++代码。
C++经常需要连接C对象文件中的符号,这往往导致链接上的问题。解决方法是明确地通知C++编译器不对哪些需要由C对象文件中的符号来解析的未定义符号进行名称改编。这可以通过在相应声明中使用extern "C"
编译器指令来实现。
如下声明,可使函数factorail()被C++编译器编译后,仍可链接到C库中,避免链接时出现未定义符号。
//main.ccextern "C"{ unsigned factorial(unsigned n);}
3 识别编译器和连接器版本不匹配的问题
编译器不匹配的症状是:连接器报错(有符号丢失),但这些符号在对象文件或库中都存在。
当试图链接不同的编译器(或版本)生成的对象文件时,就会发生对象的不匹配问题。最常见的情况是必须使用那些无法获得源代码的对象文件或库,例如第三方库。这种情况下,简单的修复方法不再有效,即无法使用相同的编译器和连接器重头开始构建。
可以使用nm对两个对象文件的符号表进行分析:一是包含未解析符号的表,二是具有相应定义符号的表;将得出如下结果:已反改编的用户级别的符号是相同的,而经过名称改编的符号不同。
下一步就是找出用于生出不同对象文件的编译器版本,并决定使用哪个编译器来编译和连接所有的对象文件和库。一种适用于几乎所有UNIX风格的平台的方法是在对象文件中搜索特定字符串,这些字符串给出了有关编译器版本的暗示。可用的方法是使用Unix工具(strings, grep)和编辑器(如emacs).如:
4 ldd executablefie
打印库依赖关系,可知道还有那些库未找到。
- 5 解析未定义的符号(下)
- 4 解析未定义的符号(上)
- 关于gcc-1.37.1下直接编译linux-0.11内核未定义符号的解决
- Liunx下解决动态链接库符号未定义问题
- insmod错误:符号未定义
- Linux内核未定义符号
- Visual Studio 调试(Dubug)模式下的“未定义标识符”
- Ubuntu下一种编译错误(未定义的函数)
- 编译Opal时出现大量未定义符号问题的解决
- 利用ld指令查找动态库中未定义的符号
- VS2008 中右键“转到定义”弹出“未定义符号” 的解决办法。
- Admob(6.12.x)符号未定义错误的解决方法(IOS)
- ++符号的贪心方法与左值右值和未定义表达式
- Admob(6.12.x)符号未定义错误的解决方法(IOS)
- VS2008 中右键“转到定义”弹出“未定义符号” 的解决办法。
- VS2008 中右键“转到定义”弹出“未定义符号” 的解决办法。
- visual studio 2013下无法解析外部符号的问题
- 出现LINK状态下无法解析的符号
- GreenDao数据库结构升级
- keil can't execute "c:\keil\c51\bin\c51.exe
- 关于html和css 学习
- CSU 1082: 憧憬一下集训 (线段树 扫描线)
- Azure Blob存储(1)
- 5 解析未定义的符号(下)
- _variant_t与相关类型之间的转换
- 剑指offer面七_用两个队列实现栈
- Cocoa 和 Objective-C 特性
- Android多线程机制解析
- 图片下载的两种方式
- mysql insertreplace update 的区别
- Duilib从Zip加载资源
- UITextView自定义文字属性后光标老是自动跳到末尾的问题