起因是同事更新了项目所使用的百度地图 SDK 之后,我们的 XML 解析库就没法用了。解析库每次运行到 xmlFree
函数就会跳到 baidu
开头的另一个函数里面去,然后爆出:
Pointer being freed was not allocated
看起来像是调用 libxml
的 xmlFree
函数代码,最后调用了百度提供的实现。
已知 XML 解析库和百度 SDK 都是静态库,然后 XML 解析库引用了 libxml
的 xmlFree
函数,所以很容易重现。
// in A.a, a.o
void xmlFree(void *ptr) {
}
// in B.a, b.o
#import <libxml/HTMLparser.h>
#import <libxml/xpath.h>
#import <libxml/xpathInternals.h>
void foo(void) {
xmlFree(NULL);
}
// in main executable
foo()
测试了一下,发现是 A.a 里面的 extern xmlFree
的存在,会导致在重定位阶段把 b.o 的 foo
对 xmlFree
的引用指向了 A.a 中的定义。而且这样的结果貌似是未定义行为,暂时还没搜索到具体文档说明。
顺便提一下,两个静态库函数同名 linkage 会报错;两个动态库函数同名实际调用顺序就跟动态链接顺序相关。不过这都不是什么好的工程实践,SDK 提供方还是得注意符号可见性问题。
具体到这个案例上,只能先把 SDK 降回去,因为符号可见性的改变需要 SDK 提供方执行。
题外话,说起来 SDK 提供方对命名空间缺失的漠视(符号可见性控制、category naming clash),我觉得这么些年就没几个人在意过。
— Jul 6, 2021