C++ 为什么我的boost::circular\u缓冲区在使用迭代器访问时会崩溃?

C++ 为什么我的boost::circular\u缓冲区在使用迭代器访问时会崩溃?,c++,boost,circular-buffer,C++,Boost,Circular Buffer,在下面的程序中,当我使用*(begin\u iterator+index)从循环缓冲区的前端访问元素时,我会崩溃。但是如果我使用buffer[index]访问相同的元素,崩溃就会消除。(请参见下面的两行注释)。为什么会发生这种情况 #include <boost/circular_buffer.hpp> #include <thread> auto buffer = boost::circular_buffer<int>(5000); void f1()

在下面的程序中,当我使用
*(begin\u iterator+index)
从循环缓冲区的前端访问元素时,我会崩溃。但是如果我使用
buffer[index]
访问相同的元素,崩溃就会消除。(请参见下面的两行注释)。为什么会发生这种情况

#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();
}
#包括
#包括
自动缓冲=升压::循环缓冲(5000);
void f1()
{
常数自动N=500;
while(true){
//确保缓冲区从不为空
if(buffer.size()buffer.capacity()/2){
继续;
}
静态自动k=0;
buffer.push_back(k++);
}
}
int main()
{
自动t1=std::线程{f1};
自动t2=std::线程{f2};
t1.join();
}
您正在经历的问题是,您正在读取和修改同一对象,而该对象未从多个线程同步

以这种或那种方式编码可能会消除崩溃,但程序仍然是错误的

如果我们添加互斥锁,则不会再发生崩溃:

#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();
}
#包括
#包括
#包括
boost::循环缓冲区(5000);
std::互斥mtx;
void f1()
{
常数自动N=500;
while(true){
标准:锁和防护锁(mtx);
//确保缓冲区从不为空
if(buffer.size()buffer.capacity()/2){
继续;
}
静态自动k=0;
buffer.push_back(k++);
}
}
int main()
{
自动t1=std::线程{f1};
自动t2=std::线程{f2};
t1.join();
}

谢谢。因此,我对循环缓冲区的实现细节似乎有太多的假设。我假设,因为不同的线程似乎作用于缓冲区的不同部分(前面和后面),所以它们的操作应该是线程安全的。您的回答暗示了这个假设是错误的,对吗?它不是关于缓冲区元素的。缓冲区肯定有用于开始和结束位置的内部指针,您在多个线程中共享这些指针。