读取多线程函数中的位置错误时发生访问冲突



请检查此代码中可能存在的多线程错误。有时我会犯一个错误";访问违规读取位置";在CCD_ 1行(用代码标记(。

uint64_t GetFirstAdvertisingBLEAddr()
{
std::mutex m;
std::condition_variable cv;
BluetoothLEAdvertisementWatcher advWatcher;
uint64_t addr = 0;
bool stopCalled = false;
auto recvToken = advWatcher.Received([&addr, &m, &cv](BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
ShowAdvertisement(eventArgs);
addr = eventArgs.BluetoothAddress();
watcher.Stop();
std::unique_lock l(m);
cv.notify_all(); // <----- HERE ------------------------------------
});
auto stoppedToken = advWatcher.Stopped([&stopCalled, &m, &cv](BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementWatcherStoppedEventArgs eventArgs) {
std::unique_lock l(m);
stopCalled = true;
cv.notify_all();
});
{
std::unique_lock l(m);
advWatcher.Start();
cv.wait(l, [&addr, &stopCalled, &advWatcher] { return addr != 0 && stopCalled && (advWatcher.Status() == BluetoothLEAdvertisementWatcherStatus::Aborted || advWatcher.Status() == BluetoothLEAdvertisementWatcherStatus::Stopped); });
}
// remove event handlers
advWatcher.Received(recvToken);
advWatcher.Stopped(stoppedToken);
return addr;
}

如果你需要更多的代码:

int main()
{
winrt::init_apartment();
std::wcout << "Main thread: " << std::this_thread::get_id() << std::endl;
uint64_t addr = GetFirstAdvertisingBLEAddr();
if (addr == 0) {
std::wcout << L"Failed to find advertising BLE device." << std::endl;
return 1;
}
std::wcout << "Found BLE device: " << GetDeviceName(addr) << std::endl;
BluetoothLEDevice dev = BluetoothLEDevice::FromBluetoothAddressAsync(addr).get();
GattDeviceServicesResult result = dev.GetGattServicesAsync(BluetoothCacheMode::Uncached).get();
.......

当函数GetFirstAdvertisingBLEAddr返回时,互斥对象和条件变量都超出了作用域。lambdas中捕获的变量然后悬空,读取这些变量会使程序具有未定义的行为。

一种可能的解决方法是使它们成为static:

static std::mutex m;
static std::condition_variable cv;

最新更新