станд :: векторавария - PullRequest
       13

станд :: векторавария

6 голосов
/ 29 января 2011

Этот вопрос является продолжением моего вопроса .

Вот проблемный код.

хиджра:

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

и, наконец, main.cpp:

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

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

    return 0;
}

Компиляция следующим образом (main.cpp скомпилирован с флагом отладки STL):

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

При запуске a.out происходит сбой процесса:

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

Мой 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)

Ответы [ 2 ]

12 голосов
/ 29 января 2011

Ваша проблема передает -D_GLIBCXX_DEBUG только a.cpp. Этот флаг добавляет дополнительную информацию об отладке к структурам STL, и поэтому его использование должно быть одинаковым для всех файлов в вашем проекте. В противном случае разные файлы могут не согласиться с разметкой памяти std::vector и std::string, что приведет к неопределенному поведению (в вашем случае, сбой).

1 голос
/ 30 января 2011

В своем предыдущем вопросе вы ссылаетесь на документацию GCC здесь: http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt03ch17s04.html. В этой документации говорится, что GCC libstdc ++ "поддерживает перекомпиляцию для каждого пользователя" и определяет ее следующим образом:

Перекомпиляция для использования: пользователь должен перекомпилировать части своего приложения и библиотек C ++, в зависимости от того, где должна происходить отладка, и любой другой код, взаимодействующий с этими контейнерами. Это означает, что набор модулей перевода, который обращается к конкретному стандартному экземпляру контейнера, может быть скомпилирован либо в режиме выпуска (без проверки), либо в режиме отладки (полная проверка), но все они должны быть скомпилированы одинаково; модуль перевода, который не видит, что стандартный экземпляр контейнера не нужно перекомпилировать. Это также означает, что модуль перевода A, который содержит конкретный экземпляр (скажем, std :: vector), скомпилированный в режиме выпуска, может быть связан с модулем перевода B, который содержит тот же экземпляр, скомпилированный в режиме отладки (функция отсутствует при частичной перекомпиляции ). Хотя такое поведение технически является нарушением правила единого определения, на практике эта способность имеет большое значение. Режим отладки libstdc ++ поддерживает этот уровень перекомпиляции.

Компиляция на единицу, которую вы пытаетесь сделать здесь, гласит:

Мы считаем, что этот уровень перекомпиляции на самом деле невозможен, если мы намереваемся предоставить безопасные итераторы, оставить семантику программы неизменной и не снижать производительность в режиме выпуска ....

Таким образом, мой ответ на ваш предыдущий вопрос был не совсем точным, и я прошу прощения. Я добавил в него дополнение, чтобы исправить его, и надеюсь, что это полезное предложение о том, как решить проблему с несколькими библиотеками.

...