11

私はArmにboost1.47を使用しており、Code Sourcery C ++コンパイラ(4.5.1)を使用して、Ubuntuを対象としたWindows7からのクロスコンパイルを行っています。

デバッグバージョンをコンパイルすると(つまり、アサートが有効になると)、アサートがトリガーされます。

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

リリースモードでコンパイルすると、アサーションはトリガーされず、プログラムは正常に動作します(私たちが知る限り)。

これはUbuntu10.xArmボードで発生しています。

したがって、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

PTHREAD_MUTEX_INITIALIZERと同様に、BOOST_HAS_THREADSが設定されていることを確認しました。

ブーストを介してデバッガーをフォローしようとしましたが、テンプレート化されたコードであり、アセンブリをフォローするのはかなり困難でしたが、基本的に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です。(__countunsigned int)は0x6078af00であり、__owner(int)は0x6078af00です。

これは、どういうわけかこのミューテックスの初期化が実行されなかったと私に思わせます。それか完全に破損していますが、デバッグブーストライブラリとリンクしたときにアサートがなかったため、初期化を逃す傾向があります。

ここで、照会されているミューテックスは、正規表現をスレッドセーフにするために使用されるグローバル/静的であり、どういうわけか初期化されていないと想定しています。

  • 誰かが似たようなものに遭遇したことがありますか?ミューテックスの初期化を確実にするためにUbuntuに必要な追加の手順はありますか?
  • 私の実装の仮定は正しいですか?
  • それが正しければ、誰かがこのミューテックスが宣言されている場所と、初期化が行われている場所を教えてもらえますか?
  • さらなるデバッグ手順に関する提案はありますか?どういうわけかソースをダウンロードして、そこにトレースを入れて再構築する必要があるかもしれないと思っています(この時点に到達する前にStackOverflowが役立つことを願っています)
4

2 に答える 2

1

これらのオフセットを使用して、メモリ内のデータを検査しました。値は意味がありませんでした。たとえば、__data.__lockフィールド(int)は0xb086b580です。(__countunsigned> int)は0x6078af00であり、__owner(int)は0x6078af00です。

これは、コードのさまざまな部分が、さまざまな構造の大きさについてさまざまな見方をしているように思えます。確認すべき点:

  • #defineデータ構造を拡大するものの、コードベース全体で一貫して設定されていないものはありますか?(Windowsでは、_SECURE_SCLこの種のバグで有名です)
  • 構造物のパッキングはありますか?ヘッダーのどこかに設定#pragma packし、ヘッダーの最後で設定を解除するのを忘れた場合、その後に含まれるデータ構造は、プログラムの他の場所とは異なるレイアウトになります。
于 2012-11-14T16:33:48.873 に答える
1

Boostのようなよく知られた、十分にテストされたライブラリで本当に本当に独特なランタイムクラッシュが発生したときに最初にチェックすることの1つは、ヘッダー/ライブラリ構成の不一致があるかどうかです。IMHOは、ヘッダーに_DEBUGまたはNDEBUGを配置し、特にバイナリレイアウトに影響を与える方法で構造内に配置することは、アンチパターンです。理想的には、_DEBUG、DEBUG、Debug、Debug、NDEBUGなどを定義するかどうかに関係なく、同じ.libを使用できる必要があります(デバッグシンボルが必要かどうかに基づいて.libを選択できるようにするため、デバッグシンボルがあるかどうかではありません)。ヘッダー定義に一致します)。残念ながら、これが常に当てはまるとは限りません。

于 2012-12-06T20:18:37.187 に答える