记录一个 zip_open 函数签名冲突的问题
记录一个 zip_open 函数签名冲突的问题
在设计 c++ sdk 时,我们常常会隐藏大部分接口,只保留要暴露给客户的那部分接口,但是如果 我们的 sdk 依赖了第三方库,第三库编译时如果不带 hidden 属性,第三方库的函数签名就会被导出,如果客户刚好有同名的函数,就有可能会链接到我们引入的第三方库,从而出现一些未知的问题。下面记录一下我是如何发现这个问题并解决的。
问题发现
在下面的伪代码中,客户在 func 函数中调用了 sdk_api,客户的另一个 sdk 里调用了 zip_open 函数,且客户把调用 func 函数的地方注释掉了的,但是程序运行后就崩溃了,奇怪的是,把 func 里的 sdk_api 函数注释掉,客户的程序就正常运行。所以猜测是编译的时候,客户调用的zip_open 链接到了我们的 sdk 里的某个库上了。
1
2
3
4
5
6
7
8
9
10
11
void func() {
sdk_api(); // sdk 里的 open 函数
}
int main() {
// func();
zip_open(); // 另一个库里的 open 函数
return 0;
}
问题解决
我使用 readelf -s libmysdk.so | grep zip_open
发现我们的库里却是有 zip_open 这么个函数,且 zip_open 函数是 GLOBAL + DEFAULT, 也就是全局导出的,所以在编译第三方库的时候,我们给 gcc 或者 g++ 加入了 hidden 属性就解决了。如下:
1
2
3
4
5
6
target_compile_options(
${PROJECT_NAME} PRIVATE
$<$<CONFIG:DEBUG>: -g -fvisibility=hidden>
$<$<CONFIG:RELEASE>: -DNDEBUG -fvisibility=hidden>
)
本文由作者按照 CC BY 4.0 进行授权