使用 -O1 优化标志编译项目时共享库崩溃

Shared library crash when project compiled with -O1 optimization flag

本文关键字:共享 崩溃 项目 编译 -O1 优化 标志 使用      更新时间:2023-10-16

问题:

我正在将新的共享库连接到项目。它加载了运行时动态链接。
这个新的共享库正在调用另一个共享库。

如果项目是用-O0标志编译的 - 一切正常。
如果项目是用-O1标志编译的 - 这个新库调用的库将获得

无效的free((/delete/delete[]/realloc((

崩溃总是与std::stringbasic_stringstd::basic_stringbuf有关。

被啄了什么:

Valgrind在崩溃前在应用程序中没有出现任何问题。

我尝试:

  • 将库从运行时动态链接更改为加载时动态链接
  • 检查 lib 是否使用与我的相同的 gcc 编译 (4.4.7( - 似乎是这样,至少 grep 在 .so 文件中找到了 GCC 4.4.7。

回溯

从Valgrind运行:核心转储堆栈具有各种底部,但上部通常如下所示:

==46601== Invalid free() / delete / delete[] / realloc()
==46601==    at 0x4C287CA: operator delete(void*) (vg_replace_malloc.c:507)
==46601==    by 0xF5BE9A6: std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) (in /usr/lib64/libstdc++.so.6.0.13)
==46601==    by 0xF5C2AB4: std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) (in /usr/lib64/libstdc++.so.6.0.13)
==46601==    by 0xF5A8C7F: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib64/libstdc++.so.6.0.13)
==46601==    by 0xF5A8E25: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib64/libstdc++.so.6.0.13)
==46601==    by 0xF5BC43D: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib64/libstdc++.so.6.0.13)
.......
==46601==  Address 0xf81a2c0 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
==46601== Invalid free() / delete / delete[] / realloc()
==46601==    at 0x4C287CA: operator delete(void*) (vg_replace_malloc.c:507)
==46601==    by 0xF5C4564: std::string::assign(std::string const&) (in /usr/lib64/libstdc++.so.6.0.13)
==46601==    by 0x21632E52: operator= (basic_string.h:511)
==46601==    by 0x21632E52: str (sstream:129)
==46601==    by 0x21632E52: str (sstream:557)
.........
==46601==  Address 0xf81a2c0 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
==46601== Invalid free() / delete / delete[] / realloc()
==46601==    at 0x4C287CA: operator delete(void*) (vg_replace_malloc.c:507)
==46601==    by 0x2308A103: _M_dispose (basic_string.h:236)
==46601==    by 0x2308A103: ~basic_string (basic_string.h:503)
.......
==46601==  Address 0x67b2c0 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE@@GLIBCXX_3.4"

编辑:
D_GLIBCXX_FULLY_DYNAMIC_STRING宏有所帮助。
现在
my project -O1so.file -O0作品
my project -O1so.file -O1失败

问题

我没有这些库的代码。 我想知道我还能做些什么来解决这个问题。
调查的下一步应该是什么?

调查的下一步应该是什么?

您应该开始调试。 通常,错误在-O0时"侥幸逃脱",只是在优化稍微加快时才会受到重创。

因为我不知道你的代码,我只能猜测。

我假设您创建了某种仅由共享库使用的对象。可能是某种样板。你把它传递给你的共享库,它会对它做一些事情,然后删除它。

由于您从未在自己的代码中读取此变量,因此编译器很有可能将其优化掉。

要解决您的问题,您必须找到该特定变量并用volatile标记它,以防止它的形式被优化掉。

祝你好运。

$ c++filt _ZNSs4_Rep20_S_empty_rep_storageE
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_S_empty_rep_storage

_S_empty_rep_storage声明为:

// The following storage is init'd to 0 by the linker, resulting
// (carefully) in an empty string with one reference.
static size_type _S_empty_rep_storage[];

并定义为:

// Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
// at static init time (before static ctors are run).
template<typename _CharT, typename _Traits, typename _Alloc>
typename basic_string<_CharT, _Traits, _Alloc>::size_type
basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
(sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
sizeof(size_type)];

看起来您加载的共享库具有另一个(较旧的(_S_empty_rep_storage定义。在旧版本的 GNU C++库中,_S_empty_rep_storage曾经是动态分配的,这就是为什么该共享库试图执行delete _S_empty_rep_storage并崩溃的原因。

解决方法是针对使用相同C++编译器和链接器选项使用的C++库重新编译共享库。

我得到了第 3 个 pt 库源代码,事实证明它也确实 dlopen 并且发生了以下错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42679