首页 > 解决方案 > 在发布版本(O3)上调用“libucis.so”时“free():无效指针”,我的代码从未到达

问题描述

我正在做一个大型项目并做出了相对较小的贡献:一个由 C 代码调用的 C++ 新类。在添加我对项目的贡献后,我发现调试构建完美无缺,而发布构建仅在大约 30 个测试用例(总共 20k+)上失败,其中调用了“libucis.so”的一些函数。相同代码库的调试和发布版本上的“valgrind”令人惊讶地显示出差异:在调试版本中没有发现无效访问,而发布版本就是这种情况。一些典型的 valgrind 错误如下所示:

==220335== Invalid free() / delete / delete[] / realloc()
==220335==    at 0x508D17D: operator delete(void*) (vg_replace_malloc.c:576)
==220335==    by 0x5588587: _M_dispose (basic_string.h:2765)
==220335==    by 0x5588587: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (basic_string.tcc:927)
==220335==    by 0x5588A4D: std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) (basic_string.tcc:1124)
*****some functions of libucsi.so not shown*****

==220335== Invalid free() / delete / delete[] / realloc()
==220335==    at 0x508D17D: operator delete(void*) (vg_replace_malloc.c:576)
==220335==    by 0x5589004: _M_dispose (basic_string.h:2765)
==220335==    by 0x5589004: std::string::reserve(unsigned long) (basic_string.tcc:951)
*****some functions of libucsi.so not shown*****

更重要的是,我确认我的代码(C 包装器中的类方法)从未在报告上述类似错误的所有失败测试用例中被调用。并且所有 valgrind 无效访问错误都发生在 STL 中的 basic_string 类上。

关于我的课程:SQLite 数据库编写器。包括向量和字符串标题。

我已经进行了广泛的搜索,无论是在线还是离线......一些提示将不胜感激。

标签: c++

解决方案


问题终于解决了。以下是调查和解决方案的总结。

在无功而返之后,我决定一无所有地测试我的类:只保留具有空定义和必要返回的函数成员,并注释所有“冗余”的东西。成功通过了所有剩余的约 30 个测试用例。然后我逐渐取消注释我的代码,最终我发现每当我使用 std::string 时都会发生错误,即使使用像“std::string s;”这样的单个声明也是如此。基于进一步的搜索,我认为问题是由于“libucis.so”是用不同版本的 stdc++ 编译的。而且我知道 libucis.so 不是我们编译的,而是由第三方提供的。然后我回到我的 makefile,并丢弃了所有不必要的库/头文件搜索路径。结果是编译我的代码的字符数从 ~5000 减少到只有 281。增量重建整个项目,问题解决。呸...

更新:根本原因可能与上面的讨论有所不同。最终我发现用 -fPIC 编译我的 C++11 代码解决了这个问题。但是问题是目标中包含的其他 C 代码没有使用 -fPIC 编译...那么为什么我的 C++11 代码是唯一需要使用 -fPIC 选项编译的人,而不是其余的(20+ 源代码文件)C 代码?


推荐阅读