Search code examples
ccircular-buffer

Circular buffer does not give the correct size of the buffer after 6-th element


I have written the code for the circular buffer in C and it works well until some extent. I took the size of the buffer being equal to 10. When I fill the buffer till element 6 - it works fine. But at the moment when I fill the 7-th element - I get the result "The size of the buffer is equal to 767". For the element 8 - it does not work. I use "head" to write and "tail" to extract values. Could you please help me with this?

#include<stdio.h>
#include<stdint.h>
#include <stdbool.h>


typedef struct RingBuffer {
   uint16_t* buffer;
   size_t head;
   size_t tail;
   size_t max;
   bool full;

}*cbuf_handle_t;

cbuf_handle_t init_RingBuffer (uint8_t* buffer, size_t size){

   cbuf_handle_t cbuf = malloc (sizeof(cbuf_handle_t));
   cbuf->buffer = buffer;
   cbuf->max = size;
   return cbuf;

}


void RingBuffer_free(cbuf_handle_t cbuf){

   free(cbuf);
}

void RingBuffer_reset(cbuf_handle_t cbuf){
   cbuf->head = 0;
   cbuf->tail = 0;
   cbuf->full = false;
   }

bool RingBuffer_full (cbuf_handle_t cbuf){

   return cbuf->full;
}

bool RingBuffer_empty(cbuf_handle_t cbuf){

       return (!cbuf->full && (cbuf->tail == cbuf->head));
}

size_t RingBuffer_Capacity(cbuf_handle_t cbuf){
   return cbuf->max;
}

size_t RingBuffer_size(cbuf_handle_t cbuf){
   size_t size = cbuf->max;

   if (!cbuf->full){
   if (cbuf->head >= cbuf->tail)
       {
       size = (cbuf->head - cbuf->tail);}
       else
       {
       size = (cbuf->head - cbuf->tail + cbuf->max);
       }
       }
        return size;
   }



void RingBuffer_AdvancePointer(cbuf_handle_t cbuf){
   if (cbuf->full){
       cbuf->tail = (cbuf->tail+1)%cbuf->max;
   }

   cbuf->head = (cbuf->head + 1)%cbuf->max;
   cbuf->full = (cbuf->head == cbuf->tail);
}

void RingBuffer_retreatPointer (cbuf_handle_t cbuf){
   cbuf->full = false;
   cbuf->tail = (cbuf->tail + 1)%cbuf->max;
}

void RingBuffer_addValue (cbuf_handle_t cbuf, uint8_t data){
   cbuf->buffer[cbuf->head] = data;
   RingBuffer_AdvancePointer(cbuf);


   }

int RingBuffer_Remove (cbuf_handle_t cbuf, uint8_t *data){
   int r = -1;
   if (!RingBuffer_empty(cbuf)){
       *data = cbuf->buffer[cbuf->tail];
       RingBuffer_retreatPointer(cbuf);
       r = 0;
   }
   return r;
}



int main (){



uint8_t arr[10];
cbuf_handle_t cpt = init_RingBuffer(arr, 10);

//initialzie the buffer, tail and head and max

int i = 0;
RingBuffer_reset(cpt);


for ( i = 0 ; i< 6; i++){
   RingBuffer_addValue(cpt, i);
}


size_t size = RingBuffer_size(cpt);
printf("The size of the buffer %d", size);
}


Thank you in advance!

Regards

Rostyslav


Solution

  • As said in comments, the declaration of the structure as a pointer is generally not recommended. However you can fix that bug by changing the way you allocate it using malloc :

    cbuf_handle_t cbuf = malloc (sizeof(*cbuf));
    

    This is because, cbuf being a pointer to the structure, if you dereference it you get the structure and thus its real size when you pass it to sizeof.