调用线性化后,奇怪的提升循环缓冲行为

时间:2016-11-11 13:02:46

标签: c++ boost circular-buffer

我在boost::circular_buffer上实现了一个提取方法,它只将n个元素复制到destination向量,然后从循环缓冲区中删除这些n个元素(因此它的内部指针)更新,标记可以再次写入的位置):

void CircularBuffer::extract(const unsigned int n, vector<complex<float>> *destination){
    // Wait until the buffer is not empty
    std::unique_lock<mutex> l(lock);
    notEmpty.wait(l, [this, n](){
        return (int)(circularBuffer.size() - n) >= 0;
    });

    // We must copy n elements from a linearized version of the buffer
    memcpy(destination, circularBuffer.linearize(), n);
    // Remove extracted elements from circular buffer
    circularBuffer.erase(circularBuffer.begin(), circularBuffer.begin() + n); //SIGSEGV

    // Not full any more
    notFull.notify_one();
}

调用erase方法时,会出现分段错误。

我使用以下尺寸:

n = 9000
circularBuffer.size() = 9000 (at the moment when extract method is called)
circularBUffer.capacity() = 90000

但是,只要memcpy行被执行,我猜是因为linearize调用,所有内容都混乱了,调试器显示:

circularBuffer.size() = 3238197033 (Hex: Hex:0xc102f729)
circularBUffer.capacity() = 18446744073434141805 (Hex:0xffffffffef95946d)

我可能还没有理解线性化方法是如何工作的,但无论如何它看起来都很奇怪。

如果我继续,并且调用擦除方法,则会引发分段错误并且程序结束。如果我删除的数据多于缓冲区容量,我可以理解它,但事实并非如此。

任何帮助?

1 个答案:

答案 0 :(得分:3)

你的记忆错了。您正在将数据复制到vector对象本身的地址中,而不是将其复制到向量指向的位置。在调用此函数之前,请确保调用vector::reserve以避免不必要的内存解除分配和分配。

我会将函数重写为:

    #include <iterator>

    void CircularBuffer::extract(const unsigned int n, 
                               vector<complex<float>>& destination)
    {
        // Wait until the buffer is not empty
        std::unique_lock<mutex> l(lock);
        notEmpty.wait(l, [this, n](){
            return (int)(circularBuffer.size() - n) >= 0;
        });

        auto cb_ptr = circularBuffer.linearize();
        assert (cb_ptr);

        std::copy(cb_ptr, cb_ptr + n, std::back_inserter(destination));

        circularBuffer.erase(circularBuffer.begin(), circularBuffer.begin() + n); 

        // Not full any more
        notFull.notify_one();
    }