这个问题的背景是我之前的问题:
non-member function pointer as a callback in API to member function(可能不相关)。
回调启动一个写入一些数据的线程。还有另一个线程读取相同的数据,并导致某些崩溃。
我只是参加了多线程速成类(感谢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.
该锁在构造函数中起作用,但在回调函数中无效。知道出了什么问题吗?我应该看什么? (以及如何完善我的问题)
谢谢!
其他相关线程
Cannot access private member declared in class 'QReadWriteLock'Error 1 error 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);
最佳答案
为什么需要足够的代码示例的好例子。
如果我正确解释了您的回调语法,
set_stream_callback(&streamCBWrapper,&mid);
将streamCBWrapper
设置为回调函数,而&mid
是userdata
的指针。
在回调中,您实际上正在将一个指向int
的指针转换为MyClass
,然后尝试访问不存在的对象的成员变量。
确保将MyClass
实例传递给您的回调。我认为这将是this
在您的情况下。