2011-01-29 3 views
6

Этот вопрос является продолжением my question.std :: vector <std::string> crash

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

ах:

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

Мой НКУ:

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) 

ответ

1

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

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

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

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

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

12

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

+0

Это то, что я понимаю.Итак, как бы вы прокомпилировали ответы на мой вопрос http://stackoverflow.com/questions/4764048/stl-and-release-debug-library-mess. Разве я не неправильно понял ответы, или мой вопрос непонятен/правильный? – dimba

+2

Чтобы быть ясным, в общем случае флаги должны устанавливаться раз и навсегда и последовательно применяться ко всему набору файлов, которые вы хотите скомпилировать. –

+0

@Matthieu Не могли бы вы также упомянуть комментарий выше – dimba