Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::vector<std::string> crash

This question is continuation of my question.

Here is problematic code.

a.h:

#include <string>
#include <vector>

std::vector<std::string> foo();

a.cpp

#include "a.h"

std::vector<std::string> foo()
{
   std::vector<std::string> v;
   return v;
}

and finally main.cpp:

#include "a.h"
#include <iostream>

int main()
{
    std::vector<std::string> s = foo();

    return 0;
}

Compilation as following (main.cpp is compiled with STL debugging flag):

g++ -c a.cpp
g++ -D_GLIBCXX_DEBUG main.cpp a.o

When running a.out, process crashes:

Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0  0x00007fe355998c43 in __gnu_debug::_Safe_iterator_base::_M_detach_single() () from /usr/lib64/libstdc++.so.6
(gdb) bt
#0  0x00007fe355998c43 in __gnu_debug::_Safe_iterator_base::_M_detach_single() () from /usr/lib64/libstdc++.so.6
#1  0x00007fe355999ebc in __gnu_debug::_Safe_sequence_base::_M_detach_all() () from /usr/lib64/libstdc++.so.6
#2  0x0000000000400cac in __gnu_debug::_Safe_sequence_base::~_Safe_sequence_base() ()
#3  0x0000000000400cc6 in __gnu_debug::_Safe_sequence<std::__debug::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::~_Safe_sequence() ()
#4  0x0000000000400ce7 in std::__debug::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector() ()
#5  0x0000000000400c35 in main ()

My gcc:

Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.4 --enable-ssp --disable-libssp --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --program-suffix=-4.4 --enable-linux-futex --without-system-libunwind --with-arch-32=i586 --with-tune=generic --build=x86_64-suse-linux
Thread model: posix
gcc version 4.4.1 [gcc-4_4-branch revision 150839] (SUSE Linux)
like image 219
dimba Avatar asked Jan 29 '11 10:01

dimba


2 Answers

Your problem is passing -D_GLIBCXX_DEBUG to only a.cpp. This flag adds additional debugging information to STL structures, and as such its usage must be consistent across all files in your project. Otherwise, different files disagree about the memory layout of std::vector and std::string, resulting in undefined behavior (a crash, in your case).

like image 79
bdonlan Avatar answered Oct 18 '22 13:10

bdonlan


In your previous question, you reference the GCC documentation here: http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt03ch17s04.html. That documentation states that the GCC libstdc++ "supports per-user recompilation", and defines it as follows:

Per-use recompilation: The user must recompile the parts of his or her application and the C++ libraries it depends on where debugging should occur, and any other code that interacts with those containers. This means that a set of translation units that accesses a particular standard container instance may either be compiled in release mode (no checking) or debug mode (full checking), but must all be compiled in the same way; a translation unit that does not see that standard container instance need not be recompiled. This also means that a translation unit A that contains a particular instantiation (say, std::vector) compiled in release mode can be linked against a translation unit B that contains the same instantiation compiled in debug mode (a feature not present with partial recompilation). While this behavior is technically a violation of the One Definition Rule, this ability tends to be very important in practice. The libstdc++ debug mode supports this level of recompilation.

Of per-unit compilation, which is what you're trying to do here, it says:

We believe that this level of recompilation is in fact not possible if we intend to supply safe iterators, leave the program semantics unchanged, and not regress in performance under release mode....

Thus, my answer on your previous question was not entirely accurate, and I apologize. I've added an addendum to it to correct it, with what I hope is a useful suggestion about how to solve the multi-library problem there.

like image 31
Brooks Moses Avatar answered Oct 18 '22 12:10

Brooks Moses