0

A piece of C++ code that uses std::stringstream fails when I change the runtime libraries to older versions.

I have two environments that I call patched and obsolete

The Patched environment is SLES 11 SP3

  • GCC 4.3
  • GNU LIBC 2.11
  • GNU LIBSTDC++ 4.7.2

The Obsolete environment is SLES 11

  • GCC 4.3
  • GNU LIBC 2.9
  • GNU LIBSTDC++ 4.3.3

When I compile and run the following code in the patched environment it compiles and terminates correctly, however the binary compiled in the patched environment dumps core when it is being run in the obsolete environment.

#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;
}

The code is compiled with the following options -Wall -O3 -g, however the result does not seem to depend on the optimization level.

In the obsolete environment the code fails with

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

Analyzing the core file I can extract the following stack trace:

#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

This core dump suggests that the code fails while converting the number into string.

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.

Dima Chubarov
  • 16,199
  • 6
  • 40
  • 76

2 Answers2

2

What you want is to compile for one specific environment and being able to execute in another specific but different environment.

I am afraid you are being a pioneer here. I am not saying it is impossible, but I am saying this does not make much sense as C++ was not designed to be platform independent (like Java for example).

So you risk to put a lot of effort into something that maybe is easier to solve by simply having two compilations for two different environments.

As far as I can judge (but no guarantee) you won't find a viable solution for this.

In other SO questions and answers I saw many suggesting to use Valgrind when that error comes up. If you want to dig deeper into that maybe start there.

Ely
  • 10,860
  • 4
  • 43
  • 64
  • 1
    I think the best approach would be to compile on the oldest platform. Then normally, it would run in the newer. – user2672165 Jul 03 '15 at 07:17
1

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

As an experiment deploy glibc 2.11 on your obsolete platform (Multiple glibc libraries on a single host) and run your program on your obsolete platform with glibc 2.11.

GNU LIBSTDC++ 4.7.2

And also copy libstdc++ 4.7.2 to a directory with your program from the patched environment.

Community
  • 1
  • 1
  • Thank you, following your suggestion I recompiled the code specifying a local copy of the new dynamic linker, copied the library dependencies and the problem disappeared. – Dima Chubarov Jul 03 '15 at 15:26
  • 2
    No need to copy libstdc++, just use `-static-libstdc++`. – Thomas Jul 04 '15 at 11:26