微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决多线程函数中的访问冲突读取位置错误

请检查此代码是否存在多线程错误。有时我在第 cv.notify_all(); 行(代码标记)收到错误“访问冲突读取位置”。

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,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 返回时,互斥量和条件变量都超出范围。 lambda 表达式中捕获的变量然后悬空,读取这些变量会使您的程序具有未定义的行为。

一种可能的解决方法是让它们static

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。