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

Shared library crash when project compiled with -O1 optimization flag

问题:

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

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

Invalid free() / delete / delete[] / realloc()

崩溃总是与 std::stringbasic_stringstd::basic_stringbuf 相关联。

检查了什么:

Valgrind 在崩溃前没有显示任何应用程序问题。

我尝试过:

回溯

来自 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 -O1 : so.file -O0 有效
my project -O1 : so.file -O1 失败

问题

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

What should be next steps in investigation?

你应该开始调试了。通常 -O0 的错误 "get away it" 只会在优化稍微启动时受到严重打击。

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

我假设您创建了某种仅供您的共享库使用的对象。可能是某种样板。你将它传递给你的共享库,它会对其进行一些处理,然后将其删除。

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

要解决您的问题,您必须找到该特定变量并将其标记为 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-rd pt 库源,结果发现它也执行 dlopen 并出现以下错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42679