Утверждение 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 может мне помочь, прежде чем я доберусь до этого момента)
Ответы
Ответ 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
в любом месте заголовка и забудете отменить его в конце заголовка, любые структуры данных, включенные после этого, будут иметь разный макет, чем в других местах вашей программы.