2

この質問の背景には、以前の質問があります。 非メンバー関数ポインターが API 内のメンバー関数へのコールバックとして使用されています(無関係かもしれません)。

コールバックは、データを書き込むスレッドを起動します。同じデータを読み取る別のスレッドがあり、その結果、いくつかのクラッシュが発生します。マルチスレッドの集中講座を受講したところです (SO に感謝します)。データがライターとリーダーによって同時にアクセスされないことを保証する試みを次に示します。Qt (QReadWriteLock) のミューテックス メカニズムを使用しています。

#include <QSharedPointer>
#include <QReadWriteLock>

Class MyClass
{
public:
  MyClass();
  bool open();
  float getData();
  void streamCB(void* userdata);

protected:
  float private_data_;
  QSharedPointer<QReadWriteLock> lock_;
};

// callback wrapper from non-member C API to member function void
__stdcall streamCBWrapper(void* userdata)
{
   static_cast<MyClass*>(userdata)->streamCB(userdata);
}

// constructor
MyClass::MyClass()
{
  lock_ = QSharedPointer<QReadWriteLock>(new QReadWriteLock());
  lock_->lockForWrite();
  private_data_ = getData();
  lock_->unlock();
}

// member callback
void MyClass:streamCB(void* userdata)
{
  float a = getData(); 
  lock_->lockForWrite(); //*** fails here
  private_data_ = a;
  lock_->unlock();
}

プログラムの実行中にセグメンテーション違反が発生しました。VSデバッガーはAccess violation writing location 0x00fedbed.、私がマークした行に、//*** fails here. ロックはコンストラクターで機能しましたが、コールバックでは機能しませんでした。

何がうまくいかないのですか?何を見ればいいですか?(そしてどうすれば私の質問を絞り込むことができますか)ありがとう!

その他の関連スレッド クラス 'QReadWriteLock'Error 1 エラー C2248: 'QReadWriteLock::QReadWriteLock' で宣言されたプライベート メンバーにアクセスできません(私は QSharedPointer の提案を使用しました)

編集1: コールバックが設定されています

bool MyClass::open()
{
  // stuffs
  int mid = 0;
  set_stream_callback(&streamCBWrapper, &mid);
  // more stuffs
  return true;
}

編集 2: すべての提案に感謝します。私の間違いは、ミューテックスが原因ではなく、API を理解していないことが原因でしょうか? 私はかなり混乱しています..これはset_stream_callbackのAPIドキュメントです。

typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);

/*! @brief Register a callback to be invoked when all subscribed fields have been updated
 *
 *  @param streamCB pointer to callback function
 *  @param userdata pointer to private data to be passed back as argument to callback
 *  @return 0 if successful, error code otherwise
 */
__declspec(dllimport) int __stdcall set_stream_callback(
    STREAM_CALLBACK streamCB, void *userdata);
4

2 に答える 2

1

基本的に、スレッドの問題のように聞こえます。とにかくQtミ​​ューテックスを使用しているので、Qtのスレッドメカニズムを使用し、スレッド間でシグナルとスロットを送信することを検討してください。ここここの提案に従う限り、それらはかなりよく文書化されており、使いやすいです。

于 2012-11-13T18:16:57.617 に答える
1

十分なコード例が必要な理由の良い例。

コールバック構文を正しく解釈すると、

set_stream_callback(&streamCBWrapper, &mid);

streamCBWrapperはコールバック関数として設定され、&midはへのポインタuserdataです。

コールバックでは、実際にはへのポインターをキャストしてintからMyClass、存在しないオブジェクトのメンバー変数にアクセスしようとしています。

MyClassのインスタンスをコールバックに渡すようにしてください。これはthisあなたの場合だと思います。

于 2012-11-13T16:40:20.137 に答える