"double free or corruption" 使用旧的 glibc 和 libstdc++ 库版本时

"double free or corruption" when using old glibc and libstdc++ library versions

当我将 运行time 库更改为旧版本时,一段使用 std::stringstream 的 C++ 代码失败。

我有两个环境,我称之为 patchedobsolete

补丁环境是SLES 11 SP3

过时 环境是 SLES 11

当我在 patched 环境中编译和 运行 以下代码时,它编译并正确终止,但是在 patched 环境在 过时的 环境中 运行 时会转储核心。

#include <string>      
#include <iostream>    
#include <sstream>     

using namespace std;

template<class T> inline string toS(const T &t){ 
      stringstream ss; 
      ss<<t; 
      return ss.str();} 

int main(){
  string s = "And the answer is: " + toS(42) ;
  cout << s << endl;
  return 0;
}

代码是使用以下选项编译的 -Wall -O3 -g,但结果似乎并不取决于优化级别。

过时的 环境中,代码失败

*** glibc detected *** ./a.out: double free or corruption (out): 0x0000000000603440 ***

分析核心文件我可以提取以下堆栈跟踪:

#4  0x00002b9b1f86ac26 in free () from /lib64/libc.so.6
#5  0x00002b9b1f119c66 in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) () from /usr/lib64/libstdc++.so.6
#6  0x00002b9b1f11deb8 in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) () from /usr/lib64/libstdc++.so.6
#7  0x00002b9b1f103b6d in 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 () from /usr/lib64/libstdc++.so.6
#8  0x00002b9b1f103c87 in 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 () from /usr/lib64/libstdc++.so.6
#9  0x00002b9b1f1156cc in std::ostream& std::ostream::_M_insert<long>(long) ()
   from /usr/lib64/libstdc++.so.6
#10 0x0000000000401877 in toS<int> (t=@0x7fff8bc4d6d8) at strstr.cxx:7
#11 0x0000000000401468 in main () at strstr.cxx:1

此核心转储表明代码在将数字转换为字符串时失败。

我想了解发生了什么,以便修改代码,以便如果在 已修补 环境中编译,它将 运行 在 已过时.

你想要的是为一个特定的环境编译并能够在另一个特定但不同的环境中执行。

恐怕你是这里的先驱。我并不是说这是不可能的,但我是说这没有多大意义,因为 C++ 并非设计为独立于平台(例如 Java)。

因此,您冒着将大量精力投入到可能更容易解决的问题上的风险,只需针对两个不同的环境进行两次编译即可。

据我判断(但不保证)你不会找到可行的解决方案。

在其他 SO 问题和答案中,我看到许多人建议在出现该错误时使用 Valgrind。如果您想更深入地研究,可以从这里开始。

I'd like to understand what is going on in order to modify the code so that if compiled in the patched environment it would run in the obsolete

作为实验,在您的过时平台 (Multiple glibc libraries on a single host) 上部署 glibc 2.11,并 运行 使用 glibc 2.11 在您的过时平台上部署您的程序。

GNU LIBSTDC++ 4.7.2

同时将 libstdc++ 4.7.2 复制到您的程序所在的目录中。