由一次 symbol lookup error 引发的思考
开发一个跨平台的项目的时候,大部分时候都是在VS下进行编码,所以也就使用了VS的解决方案来管理项目。
因为要跨平台,当时网上看scons
这个工具不错,所以在linux下就使用了scons
来作为编译脚本。
linux(gcc)下与windows(vs)下的对于链接这一步稍有不同。当目标文件是一个(共享)库的时候,VS会在链接的时候就去解析所有用到的符号,而gcc则不会,只有在生成最终可执行程序的时候才会去解析。
所以在VS下,一直都没有问题。linux下进行测试的时候也没有问题(因为不是所有的代码都被调用了)。
这几天在一次移植过程中出现了如下的问题
/a.out: symbol lookup error: ./uds_file_storage_module.so: undefined symbol: _ZN8unispace13us_ini_config9from_fileERKNS_10us_ustringEPS0_
错误很简单,就是us_ini_config::from_file
这个函数没有找到,说明没有将其添加到动态导出符号表中。(uds_file_storage_module.so是运行时动态加载的,所以编译的时候没有提示错误)
VC中导出符号需要使用到dllexport
,而gcc下则默认是不需要。所以这个问题很是疑惑。
考虑用的gcc
版本比较高,是不是它将-fvisibility
的参数默认设置为hidden
呢?查看了gnu的wiki之后也没有发现这个。
https://gcc.gnu.org/wiki/Visibility
这里还是有收获的,看到一段好的跨平台代码。
#if defined _WIN32 || defined __CYGWIN__ #ifdef BUILDING_DLL #ifdef __GNUC__ #define DLL_PUBLIC __attribute__ ((dllexport)) #else #define DLL_PUBLIC __declspec(dllexport) // 注记:实际上gcc似乎也支持这种语法。 #endif #else #ifdef __GNUC__ #define DLL_PUBLIC __attribute__ ((dllimport)) #else #define DLL_PUBLIC __declspec(dllimport) // 注记:实际上gcc似乎也支持这种语法。 #endif #endif #define DLL_LOCAL #else #if __GNUC__ >= 4 #define DLL_PUBLIC __attribute__ ((visibility ("default"))) #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define DLL_PUBLIC #define DLL_LOCAL #endif #endif extern "C" DLL_PUBLIC void function(int a); class DLL_PUBLIC SomeClass { int c; DLL_LOCAL void privateMethod(); // Only for use within this DSO public: Person(int _c) : c(_c) { } static void foo(int a); };
然后添加了__attribute__((visibility("default")))
进行修饰,发现编译的结果没有改变(md5sun判断)。
然后又在链接的时候添加-rdynamic
参数,将所有符号都添加到动态符号表,编译结果也没有变。
在仔细查看了SConstruct
脚本之后,发现问题在于没有将对应的源文件添加到脚本中。也就是编译的时候完全就没有编译us_ini_config::from_file
所在的源文件。
这样问题就很清晰明了了,修改脚本之后重新编译就可以了。
说到这里,就该反思一下了。
这个项目早期确实是直接写的Makefile
来进行编译的,使用SOURCES = $(shell find $(SRC_DIR)$(PROJECT)/ -name "*.cpp")
来自动发现cpp文件,这本来是很好的。对于贸然使用自己不熟悉的scons
,又没有进行有效的学习,这是很不好的。
对于这个项目,还是直接使用qmake
来做跨平台的编译脚本比较好。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理