Подтвердить что ты не робот

Утверждение Mutex в конструкторе regex boost

Я использую boost 1.47 для Arm, с компилятором Code Sourcery С++ (4.5.1), скремблинг из Windows 7 с таргетингом на Ubuntu.

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

pthread_mutex_lock.c:62: __pthread_mutex_lock: Assertion 'mutex->__data.__owner == 0' failed.

Компиляция в режиме выпуска, утверждение не запускается, и программа работает нормально (насколько мы можем сказать).

Это происходит под панелью управления Ubuntu 10.x.

Итак, похоже, что pthread_mutex_lock считает, что мьютекс был установлен другим потоком, чем текущий. На этом этапе моей программы мы по-прежнему однопоточны, проверены путем печати pthread_self в основном и непосредственно перед вызовом конструктора регулярных выражений. То есть, это не должно было пропустить утверждение.

Ниже приведен фрагмент кода, который вызывает проблему.

// Set connection server address and port from a URL
bool MyHttpsXmlClient::set_server_url(const std::string& server_url)
{
#ifdef BOOST_HAS_THREADS
cout <<"Boost has threads" << endl;
#else
cout <<"WARNING: boost does not support threads" << endl;
#endif
#ifdef PTHREAD_MUTEX_INITIALIZER
    cout << "pthread mutex initializer" << endl;
#endif
{
        pthread_t id = pthread_self();
        printf("regex: Current threadid: %d\n",id);
}
const boost::regex e("^((http|https)://)?([^:]*)(:([0-9]*))?"); // 2: service, 3: host, 5: port // <-- dies in here

Я подтвердил, что установлен BOOST_HAS_THREADS, как и PTHREAD_MUTEX_INITIALIZER.

Я пробовал следовать за отладчиком, но увеличил его, но это был шаблонный код, и было довольно сложно следить за сборкой, но мы в основном умираем в do_assign (черновая линия 380 в basic_regex.hpp)

basic_regex& assign(const charT* p1,
                      const charT* p2,
                      flag_type f = regex_constants::normal)
{
  return do_assign(p1, p2, f);
}

шаблонный код:

// out of line members;
// these are the only members that mutate the basic_regex object,
// and are designed to provide the strong exception guarentee
// (in the event of a throw, the state of the object remains unchanged).
//
template <class charT, class traits>
basic_regex<charT, traits>& basic_regex<charT, traits>::do_assign(const charT* p1,
                    const charT* p2,
                    flag_type f)
{
   shared_ptr<re_detail::basic_regex_implementation<charT, traits> > temp;
   if(!m_pimpl.get())
   {
      temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>());
   }
   else
   {
      temp = shared_ptr<re_detail::basic_regex_implementation<charT, traits> >(new re_detail::basic_regex_implementation<charT, traits>(m_pimpl->m_ptraits));
   }
   temp->assign(p1, p2, f);
   temp.swap(m_pimpl);
   return *this;
}

Я не уверен, какой компонент на самом деле использует мьютекс - кто-нибудь знает?

В отладчике я могу получить адрес для переменной mutex, а затем проверить (mutex->__data.__owner). Я получил смещения из бит файла компилятора /pthreadtypes.h, который показывает:

/* Data structures for mutex handling.  The structure of the attribute
   type is not exposed on purpose.  */
typedef union
{
  struct __pthread_mutex_s
  {
    int __lock;
    unsigned int __count;
    int __owner;
    /* KIND must stay at this position in the structure to maintain
       binary compatibility.  */
    int __kind;
    unsigned int __nusers;
    __extension__ union
    {
      int __spins;
      __pthread_slist_t __list;
    };
  } __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;

Я использовал эти смещения для проверки данных в памяти. Значения не имели смысла:  Например, поле __data.__lock (int) равно 0xb086b580. __count (неподписанный int) равен 0x6078af00, а __owner (int) равен 0x6078af00.

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

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

  • Кто-нибудь сталкивался с чем-то похожим? Нужен ли какой-то дополнительный шаг для Ubuntu для обеспечения инициализации мьютекса?
  • Является ли мое предположение о внедрении правильным?
  • Если это правильно, может кто-то указать мне, где этот мьютекс объявлен, и где происходит его инициализация
  • любые предложения по дальнейшим этапам отладки? Я думаю, что мне, возможно, придется каким-то образом загрузить источник и перестроить с помощью трассировки там (надеясь, что StackOverflow может мне помочь, прежде чем я доберусь до этого момента)
4b9b3361

Ответ 1

Одна из первых вещей, которые нужно проверить, когда действительно действительно характерная ошибка во время выполнения появляется в хорошо известной, хорошо протестированной библиотеке, например boost, есть ли несоответствие конфигурации заголовка/библиотеки. IMHO, помещая _DEBUG или NDEBUG в заголовки, особенно внутри структур таким образом, который влияет на их двоичную компоновку, является анти-шаблоном. В идеале мы должны иметь возможность использовать тот же .lib, определяем ли мы _DEBUG, DEBUG, Debug, Debug, NDEBUG или что-то еще (чтобы мы могли выбрать .lib на основе того, хотим ли мы иметь отладочные символы или нет, а не соответствует заголовку заголовка). К сожалению, это не всегда так.

Ответ 2

Я использовал эти смещения для проверки данных в памяти. Значения не имели смысла: Например, поле __data.__lock (int) равно 0xb086b580. __count (unsigned > int) равен 0x6078af00, а __owner (int) равен 0x6078af00.

Это звучит так, как разные части вашего кода имеют разные представления о том, насколько важны различные структуры. Некоторые вещи для проверки:

  • Есть ли #define, который расширяет структуру данных, но не постоянно устанавливается на всей вашей кодовой базе? (В Windows, _SECURE_SCL является печально известным для такого рода ошибок)
  • У вас есть какая-либо структура упаковки? Если вы установите #pragma pack в любом месте заголовка и забудете отменить его в конце заголовка, любые структуры данных, включенные после этого, будут иметь разный макет, чем в других местах вашей программы.