为什么我的 boost::circular_buffer 在使用迭代器访问时会崩溃?
Why does my boost::circular_buffer crash when accessed using an iterator?
在下面的程序中,当我使用 *(begin_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();
}
您遇到 undefined behavior 是因为您正在读取和修改同一个未与多个线程同步的对象。
以一种或另一种方式编码可能会消除崩溃,但程序仍然是错误的。
如果我们添加互斥锁,就不会再发生崩溃了:
#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();
}
在下面的程序中,当我使用 *(begin_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();
}
您遇到 undefined behavior 是因为您正在读取和修改同一个未与多个线程同步的对象。
以一种或另一种方式编码可能会消除崩溃,但程序仍然是错误的。
如果我们添加互斥锁,就不会再发生崩溃了:
#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();
}