使用<int *>类型的生产者/消费者双缓冲区如何避免段错误?
双缓冲区模板改为
<int*>后段错误的解决方法 问题根源分析
你的代码出现段错误主要有三个核心问题:
- 野指针未初始化:
main中buffer_a和buffer_b是未初始化的指针,直接执行buffer_a + num_elts属于非法内存访问,这是触发段错误的直接原因。 - 模板使用逻辑错误:原双缓冲区模板的
m_buf是两个T类型元素,当T=int*时,每个元素是指向int的指针,但你错误地将它们指向数组末尾,且未给指针分配实际内存。 - 写入操作逻辑错误:生产者线程中
**item = i的两次解引用操作,访问的是未初始化的野指针指向的内存,必然触发段错误。
解决步骤
1. 为指针分配有效内存
首先要给buffer_a和buffer_b分配能存储num_elts个int的内存空间:
int* buffer_a = new int[num_elts]; int* buffer_b = new int[num_elts];
注意使用完内存后要通过delete[]释放,避免内存泄漏。
2. 修正缓冲区指针指向
让双缓冲区的m_buf元素指向数组的起始位置,而非末尾:
buf.m_buf[0] = buffer_a; buf.m_buf[1] = buffer_b;
3. 调整生产者写入逻辑
start_writing()返回的是int**类型,指向双缓冲区中的int*元素,需要通过一次解引用拿到数组指针,再访问对应下标:
int** item_ptr = buf->start_writing(); if (item_ptr != nullptr) { (*item_ptr)[i] = i; }
完整修正代码
#include <thread> #include <cassert> #include <iostream> template<typename T> class ProducerConsumerDoubleBuffer { public: ProducerConsumerDoubleBuffer() : m_read_idx(0), m_write_idx(1) {} T* start_writing() { return &m_buf[m_write_idx]; } void end_writing() { std::swap(m_read_idx, m_write_idx); } T* start_reading() { return &m_buf[m_read_idx]; } void end_reading() {} T m_buf[2]; private: int m_read_idx; int m_write_idx; }; void processing(ProducerConsumerDoubleBuffer<int*> *const buf, int num_elts) { std::thread producer([&, num_elts]() { for (int i = 0; i != num_elts; ++i) { int** item_ptr = buf->start_writing(); if (item_ptr != nullptr) { (*item_ptr)[i] = i; } buf->end_writing(); } }); std::thread consumer([&, num_elts]() { int prev = -1; for (int i = 0; i != num_elts; ++i) { int* item = *buf->start_reading(); if (item != nullptr) { assert(item[i] > prev); prev = item[i]; std::cout << "Consumer: " << item[i] << std::endl; } buf->end_reading(); } }); producer.join(); consumer.join(); } int main(void) { int num_elts = 10; int* buffer_a = new int[num_elts]; int* buffer_b = new int[num_elts]; ProducerConsumerDoubleBuffer<int*> buf; buf.m_buf[0] = buffer_a; buf.m_buf[1] = buffer_b; processing(&buf, num_elts); delete[] buffer_a; delete[] buffer_b; return 0; }
额外建议
如果你的需求是批量处理多个元素,原单元素双缓冲区的设计并不适配。更推荐将模板参数T设为std::vector<int>,让每个缓冲区直接存储数组,这样可以避免指针操作的风险,逻辑也更清晰。
内容的提问来源于stack exchange,提问作者Mary
相关产品推荐
相关产品推荐

