You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:01:20