segfault при использовании boost :: signal с флагом -D_GLIBCXX_DEBUG - PullRequest
2 голосов
/ 01 июля 2010

Я строю с помощью g ++, и вчера один из полезных людей в SO сказал мне, чтобы компилировать с флагами -D_GLIBCXX_DEBUG и -D_GLIBCXX_DEBUG_PEDANTIC. Я так и сделал, и большую часть вчерашнего дня я потратил на настройку своего кода в соответствии с этими флагами. Теперь он жалуется на мое использование boost::signal, и я не уверен, где проблема.

У меня есть класс Yarl, в котором есть функция refresh(), которую я хочу связать с сигналом sigRefresh в другом классе EventHandler:

class Yarl
{
    private:
        void refresh();
    (...)
};

class EventHandler
{
    public:
        boost::signal<void()> sigRefresh;
    (...)
}

Затем в функции-члене Yarl у меня есть этот бит кода:

EventHandler eventHandler;
eventHandler.sigRefresh.connect(boost::bind(&Yarl::refresh, this));

До того, как я начал компилировать с этими флагами, этот код работал нормально. Теперь, когда я их использую, моя программа segfaults во второй строке.

Вот обратный след от GDB:

#0  0x001eeee6 in __gnu_debug::_Safe_iterator_base::_M_detach_single() ()
   from /usr/lib/libstdc++.so.6
#1  0x001f0555 in __gnu_debug::_Safe_sequence_base::_M_detach_all() ()
   from /usr/lib/libstdc++.so.6
#2  0x0804e8a3 in ~_Safe_sequence_base (this=0x812cda4, 
    __in_chrg=<value optimized out>)
    at /usr/include/c++/4.4/debug/safe_base.h:180
#3  0x08085af9 in __gnu_debug::_Safe_sequence<std::__debug::vector<boost::signals::trackable const*, std::allocator<boost::signals::trackable const*> > >::~_Safe_sequence() ()
#4  0x08085b44 in std::__debug::vector<boost::signals::trackable const*, std::allocator<boost::signals::trackable const*> >::~vector() ()
#5  0x080873ab in boost::signals::detail::slot_base::data_t::~data_t() ()
#6  0x080873e3 in void boost::checked_delete<boost::signals::detail::slot_base::data_t>(boost::signals::detail::slot_base::data_t*) ()
#7  0x0808802e in boost::detail::sp_counted_impl_p<boost::signals::detail::slot_base::data_t>::dispose() ()
#8  0x08083d04 in boost::detail::sp_counted_base::release (this=0x812ce30)
at /usr/local/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:145
#9  0x08083d76 in ~shared_count (this=0xbffff358, 
    __in_chrg=<value optimized out>)
    at /usr/local/boost/smart_ptr/detail/shared_count.hpp:217
#10 0x08083f70 in ~shared_ptr (this=0xbffff354, 
    __in_chrg=<value optimized out>)
    at /usr/local/boost/smart_ptr/shared_ptr.hpp:169
#11 0x080847f1 in ~slot_base (this=0xbffff354, __in_chrg=<value optimized out>)
    at /usr/local/boost/signals/slot.hpp:27
#12 0x08084829 in ~slot (this=0xbffff354, __in_chrg=<value optimized out>)
    at /usr/local/boost/signals/slot.hpp:105
#13 0x0808390f in yarl::Yarl::mainLoop (this=0xbffff3dc) at src/Yarl.cpp:408
#14 0x08083a96 in yarl::Yarl::startGame (this=0xbffff3dc) at src/Yarl.cpp:452
#15 0x08083abe in main () at src/Yarl.cpp:461

Кто-нибудь видит, что я должен исправить?

РЕДАКТИРОВАТЬ: у меня есть небольшая программа примера, который иллюстрирует проблему, как предложил Даниэль Треббиен.

Вот заголовочный файл (test.hpp):

#include <boost/bind.hpp>
#include <boost/signal.hpp>
#include <iostream>
#include <tr1/memory>

namespace yarl
{
    class Yarl
    {
        private:
            void refresh();
        public:
            void hookSignal();
    };

    namespace events
    {
        class EventHandler
        {
            public:
                boost::signal<void()> sigRefresh;
        };
    }
}

и вот реализация:

#include "test.hpp"
using namespace std;

namespace yarl
{
    void Yarl::refresh()
    {
        cout << "in refresh" << endl;
    }

    void Yarl::hookSignal()
    {
        events::EventHandler eventHandler;
        eventHandler.sigRefresh.connect(boost::bind(&Yarl::refresh, this));

        eventHandler.sigRefresh();
    }
}

int main()
{
    yarl::Yarl y;
    y.hookSignal();
}

Как и раньше, этот пример программы отлично работает при компиляции в g ++ только с флагом -g, но если я добавлю -D_GLIBCXX_DEBUG и -D_GLIBCXX_DEBUG_PEDANTIC, он будет сбой в строке eventHandler.sigRefresh.connect.


Я перекомпилировал boost с -D_GLIBCXX_DEBUG и -D_GLIBCXX_DEBUG_PEDANTIC, и это не решило проблему, но во время компиляции я заметил, что он делает что-то странное. Я скомпилировал с помощью bjam эту команду (в соответствии с этим руководством по повышению):

sudo bjam --build-dir=. --toolset=gcc --variant=debug --cxxflags=-D_GLIBCXX_DEBUG,-D_GLIBCXX_DEBUG_PEDANTIC --layout=tagged stage

, несмотря на тег --variant=debug, он все еще компилировал версии выпуска. Я также не видел упоминаний о моих флагах отладки в выходных данных. Возможно ли, что я скомпилировал это неправильно?

1 Ответ

1 голос
/ 11 июля 2010

Нужно ли иметь по-разному скомпилированные версии boost для кода выпуска и отладочного кода?

Боюсь, что у вас есть.По личному опыту, boost чрезвычайно чувствителен к изменениям флагов компилятора.Несколько лет назад проект свободного программного обеспечения, который я взламывал, должен был прекратить использовать boost::system и boost::filesystem только потому, что эти модули имеют общие библиотеки, которые не были надежно скомпилированы (дистрибьюторами Linux) с точно такими же флагами, что и наш код,Симптомы были такими же - необъяснимые сбои в правильном коде.

Из-за этого я должен рекомендовать не использовать какой-либо модуль Boost, который поставляет общую библиотеку.Когда-либо.Печально.

...