简体   繁体   English

为什么我的 boost::circular_buffer 在使用迭代器访问时会崩溃?

[英]Why does my boost::circular_buffer crash when accessed using an iterator?

In the following program, when I access elements from the front of the circular buffer using *(begin_iterator + index) I get a crash.在下面的程序中,当我使用*(begin_iterator + index)从循环缓冲区的前面访问元素时,我遇到了崩溃。 But if I access the same elements using buffer[index] , the crash is eliminated.但是,如果我使用buffer[index]访问相同的元素,则可以消除崩溃。 (See the two commented lines below). (请参阅下面的两条注释行)。 Why does this happen?为什么会这样?

#include <boost/circular_buffer.hpp>
#include <thread>

auto buffer = boost::circular_buffer<int>(5000);

void f1()
{
    const auto N = 500;

    while (true) {

        // Make sure the buffer is never empty
        if (buffer.size() < N+1) {
            continue;
        }

        auto front = buffer.begin();

        volatile auto j = int{};
        for (auto i = 0; i < N; ++i) {
            // j = *(front + i);        // un-commenting this causes a crash
            // j = buffer[i];           // un-commenting this doesn't
        }

        buffer.erase_begin(N);
    }
}
void f2()
{
    while (true) {

        // Make sure the buffer is at most half-full.
        if (buffer.size() > buffer.capacity() / 2) {
            continue;
        }

        static auto k = 0;
        buffer.push_back(k++);
    }
}

int main()
{
    auto t1 = std::thread{f1};
    auto t2 = std::thread{f2};

    t1.join();
}

You're experiencing undefined behavior because you're reading and modifying the same object unsynchronized from multiple threads.您遇到未定义的行为,因为您正在读取和修改与多个线程不同步的相同 object。

Coding it one way or another might eliminate the crash, but the program is still wrong.以一种或另一种方式对其进行编码可能会消除崩溃,但程序仍然是错误的。

If we add a mutex, then there's no crash anymore:如果我们添加一个互斥锁,那么就不会再出现崩溃了:

#include <boost/circular_buffer.hpp>
#include <thread>
#include <mutex>

boost::circular_buffer<int> buffer(5000);
std::mutex mtx;

void f1()
{
    const auto N = 500;

    while (true) {
        std::lock_guard<std::mutex> lock(mtx);

        // Make sure the buffer is never empty
        if (buffer.size() < N + 1) {
            continue;
        }

        auto front = buffer.begin();

        volatile auto j = int{};
        for (auto i = 0; i < N; ++i) {
             j = *(front + i);        // is OK now
            // j = buffer[i];         
        }

        buffer.erase_begin(N);
    }
}
void f2()
{
    while (true) {
        std::lock_guard<std::mutex> lock(mtx);

        // Make sure the buffer is at most half-full.
        if (buffer.size() > buffer.capacity() / 2) {
            continue;
        }

        static auto k = 0;
        buffer.push_back(k++);
    }
}

int main()
{
    auto t1 = std::thread{ f1 };
    auto t2 = std::thread{ f2 };

    t1.join();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM