C++使用unordered_map插入触发_Prime_rehash_policy段错误兼容问题求助
我们的应用基于C++11构建,使用另一团队开发的自定义库。自该库最近升级后,程序出现段错误,错误信息如下:
Program received signal SIGSEGV, Segmentation fault. 0x00007efc338f2ce2 in std::__detail::_Prime_rehash_policy::_M_need_rehash(unsigned long, unsigned long, unsigned long) const () from /path/share/custom_lib.so
通过GDB调试进一步定位到:
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7fc6b9ffb700 (LWP 196163)] 0x00007fc6d1364e82 in std::__detail::_Prime_rehash_policy::_M_need_rehash (this=0xb, __n_bkt=0, __n_elt=1, __n_ins=10903680147728276093) at /usr/include/c++/4.4.7/tr1_impl/hashtable_policy.h:492 492 /usr/include/c++/4.4.7/tr1_impl/hashtable_policy.h: No such file or directory.
经排查,问题根源是编译器版本不兼容:我们的开发环境使用GCC 4.8.2,而自定义库基于GCC 4.4.7编译。由于替换unordered_map为map会导致性能下降,且无法回退编译器、库开发团队也无法升级编译器,现寻求临时解决或变通方案。
临时解决方案
隔离标准库容器交互:在应用与自定义库的接口层,禁止直接传递
std::unordered_map等标准库容器。改用自定义数据结构(比如C风格的键值对数组+长度、或自定义结构体)作为交互载体,两边各自负责将自定义结构与自身的标准库容器进行转换。例如:库侧将unordered_map的键值对拷贝到自定义数组中返回,应用侧再把数组转换成自己的unordered_map,彻底切断跨版本标准库对象的直接传递。静态链接冲突的标准库组件:将应用中涉及冲突的标准库部分(比如
libstdc++中与哈希表相关的实现)静态链接,让应用使用GCC 4.8.2的标准库版本,而自定义库继续使用它自己的GCC 4.4.7版本。编译时可添加选项-static-libstdc++,但需测试是否存在其他依赖冲突;如果只想针对特定组件静态链接,也可以手动链接对应版本的静态库对象文件。替换为第三方独立哈希库:放弃使用
std::unordered_map,改用不依赖系统标准库版本的第三方哈希表实现,比如Abseil的flat_hash_map、或Boost的unordered_map(需确保Boost库是独立编译、不依赖系统libstdc++)。在应用和库的交互中统一使用这个第三方哈希表,避免跨版本标准库的兼容性问题。临时环境变量适配(风险较高):通过
LD_PRELOAD强制加载GCC 4.4.7版本的libstdc++.so,让整个进程使用旧版本的标准库。但此方法可能影响应用中其他依赖GCC 4.8.2特性的代码,仅适合临时测试,不建议生产环境使用。
内容的提问来源于stack exchange,提问作者user2655841

