6 votes

std::vector<std::string> crash

Cette question est la suite de ma question .

Voici le code qui pose problème.

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

et enfin main.cpp :

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

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

    return 0;
}

Compilation comme suit (main.cpp est compilé avec le drapeau de débogage STL) :

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

Lors de l'exécution de a.out, le processus se bloque :

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 ()

Mon 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)

12voto

bdonlan Points 90068

Votre problème est de passer -D_GLIBCXX_DEBUG à seulement a.cpp . Ce drapeau ajoute des informations de débogage supplémentaires aux structures STL, et en tant que tel, son utilisation doit être cohérente dans tous les fichiers de votre projet. Sinon, les différents fichiers ne sont pas d'accord sur la disposition de la mémoire des structures STL. std::vector y std::string ce qui entraîne un comportement indéfini (un crash, dans votre cas).

1voto

Brooks Moses Points 6205

Dans votre question précédente, vous faites référence à la documentation GCC ici : http://gcc.gnu.org/onlinedocs/libstdc++/manuel/bk01pt03ch17s04.html . Cette documentation indique que la librairie GCC libstdc++ "supporte la recompilation par utilisateur", et la définit comme suit :

Recompilation à l'usage : L'utilisateur doit recompiler les parties de son application et les bibliothèques C++ dont elle dépend où le débogage doit avoir lieu, ainsi que tout autre code qui interagit avec ces conteneurs. Cela signifie qu'un ensemble d'unités de traduction accédant à une instance de conteneur standard particulière peut être compilé en mode "release" (pas de vérification) ou en mode "debug" (vérification complète), mais doit être compilé de la même manière ; une unité de traduction qui ne voit pas cette instance de conteneur standard ne doit pas être recompilée. Cela signifie également qu'une unité de traduction A qui contient une instanciation particulière (par exemple, std::vector) compilée en mode release peut être liée à une unité de traduction B qui contient la même instanciation compilée en mode debug (une fonctionnalité qui n'existe pas avec la recompilation partielle). Bien que ce comportement soit techniquement une violation de la règle de la définition unique, cette capacité tend à être très importante en pratique. Le mode débogage de libstdc++ supporte ce niveau de recompilation.

Pour la compilation par unité, ce que vous essayez de faire ici, c'est écrit :

Nous pensons que ce niveau de recompilation n'est en fait pas possible si nous avons l'intention de fournir des itérateurs sûrs, de laisser la sémantique du programme inchangée et de ne pas régresser en termes de performances en mode release.....

Ainsi, ma réponse à votre question précédente n'était pas tout à fait exacte, et je m'en excuse. J'ai ajouté un addendum pour la corriger, avec ce que j'espère être une suggestion utile sur la façon de résoudre le problème des multi-bibliothèques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X