Search code examples
c++segmentation-faultoperator-overloadingcircular-buffertemplate-classes

C++ how to define the operator [] to write and read an item of the circular buffer


I have created a template class that implement a circular buffer. The buffer is formed of items that have a value of type T.

I want to define the operator[ ] to write and read an element of the buffer. Even when I try to read an element already inizialized the result is: Segmentation fault: 11

This is the code for operator[ ]:

// read
const T& operator[](size_type index) const {
    assert(index < _size);
    item *curr = _buffer + index;
    return curr->value;
  }
  
  // read and write
  T &operator[](size_type index) {
    assert(index < _capacity);

    item *curr = _buffer + index;

    if (index < _size) {
      return curr->value;
    }
    else {
      _size++;
      return curr->value;
    }
  }

An example of how I use operator[ ] in main.cpp:

cbuffer<int> b(4);

  std::cout << "b: " << b << std::endl;
  std::cout << "capacity: " << b.capacity() << std::endl;
  assert(b.capacity() == 4);
  std::cout << "size: " << b.size() <<
                 std::endl;
  assert(b.size() == 0);

  b[0] = 1;
  b[1] = 3;

The error occurs when I try to write a new item in the buffer.

What could be a way to define the operator[ ] that works?


Solution

  • I'm guessing somewhat, because you haven't provided enough context (it's difficult to see if a small part of a class is correct without seeing the rest of the class). But it seems that _buffer is a linked list. The next pointer in the item struct gives it away

    typedef struct item {
        T value;
        item *next;
    };
    

    But your operator[] code assumes that _buffer is an array,

    item *curr = _buffer + index;
    

    Using + on a pointer assumes that the pointer is pointing at a contiguous block of memory but because you have a linked list that's not the case for you.

    Instead you need to write a loop, that loops through your linked list until you find the correct item. Something like this

    item *curr = _buffer;
    while (index > 0) {
        curr = curr->next;
        --index;
    }
    return curr->value;