11

我正在为 Arm 使用 boost 1.47,使用 Code Sourcery C++ 编译器 (4.5.1),从针对 Ubuntu 的 Windows 7 进行交叉编译。

当我们编译调试版本(即启用断言)时,触发了一个断言:

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

在发布模式下编译,断言没有被触发并且程序工作正常(据我们所知)。

这是在 Ubuntu 10.x Arm 板下发生的。

因此,pthread_mutex_lock 似乎认为互斥锁是由与当前线程不同的线程设置的。此时在我的程序中,我们仍然是单线程的,通过在 main 中打印出 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。

我尝试通过 boost 来跟踪调试器,但它是模板代码,并且很难跟踪程序集,但我们基本上死在 do_assign 中(大约在 basic_regex.hpp 中的第 380 行)

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)。我从编译器头文件 bits/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。( __countan unsigned int) 是 0x6078af00,__owner(an int) 是 0x6078af00。

这使我认为没有执行此互斥锁的某种初始化。要么是这样,要么是完全损坏,但我倾向于错过初始化,因为当我与调试提升库链接时,没有断言。

现在,我假设正在查询的任何互斥体都是一些全局/静态的,用于使正则表达式线程安全,并且不知何故它没有被初始化。

  • 有没有人遇到过类似的事情?Ubuntu 是否需要一些额外的步骤来确保互斥体初始化?
  • 我的实现假设是否正确?
  • 如果它是正确的,有人可以指出这个互斥锁的声明位置,以及它的初始化发生在哪里
  • 关于进一步调试步骤的任何建议?我在想我可能不得不以某种方式下载源代码并在那里进行跟踪重建(希望 StackOverflow 在我到达这一点之前可以帮助我)
4

2 回答 2

1

我使用这些偏移量来检查内存中的数据。这些值没有意义:例如,__data.__lock字段(一个 int)是 0xb086b580。( __countan unsigned > int) 是 0x6078af00,__owner(an int) 是 0x6078af00。

这听起来像是代码的不同部分对各种结构的大小有不同的看法。需要检查的一些事项:

  • 有没有#define可以扩大数据结构,但在整个代码库中设置不一致?(在 Windows 上,_SECURE_SCL因此类错误而臭名昭著)
  • 你做任何结构包装吗?如果您#pragma pack在标头中的任何位置设置并忘记在标头末尾取消设置,则此后包含的任何数据结构都将具有与程序中其他位置不同的布局。
于 2012-11-14T16:33:48.873 回答
1

在像 boost 这样一个众所周知的、经过充分测试的库中出现真正特殊的运行时崩溃时,首先要检查的事情之一是是否存在头文件/库配置不匹配。恕我直言,将 _DEBUG 或 NDEBUG 放在标题中,尤其是在结构中以影响其二进制布局的方式,是一种反模式。理想情况下,无论我们定义 _DEBUG、DEBUG、Debug、 Debug 、NDEBUG 还是其他任何东西,我们都应该能够使用相同的 .lib (这样我们就可以根据是否需要调试符号来选择 .lib,而不是是否匹配标题定义)。不幸的是,情况并非总是如此。

于 2012-12-06T20:18:37.187 回答