I'm back, and it appears I still haven't quite figured out memory management in C. While trying to design an event queue I decided to build a circular buffer as an exercise. After a bit of research I am trying to model it after the following implementation I saw here on SO: https://stackoverflow.com/a/827749 .
I decided to simplify it a bit, instead of building a buffer for any data type I wanted to build one just for integers. For the most part I was able to follow the logic, although I do not understand how come the author is occasionally casting values to (char *). I've tried my program with and without the (char *) casts but it yields the same incorrect output in both cases.
Once I write past a certain point, values that should not change in my buffer are being affected, which I assume has something to do with the way I've allocated memory for the buffer. It looks like the program is writing past the buffer I've allocated in my struct, and is overwriting values that should otherwise be static. I can't for the life of me figure out how to fix the error, but I have a sneaking suspicion it's something very obvious I've managed to overlook.
Here is my code:
typedef struct Circular_buffer
{
void *buffer;
void *buffer_end;
size_t capacity; // The maximum number of items allowed in buffer
size_t count; // Current number of items in buffer
size_t item_size; //Size of each item;
void *head;
void *tail;
} Circular_buffer;
int main(void)
{
int i;
Circular_buffer my_buffer;
c_buff_init( &my_buffer, 10 );
printf("Buffer Capacity: %d\n", my_buffer.capacity);
for (i = 0; i < 7; i++) {
c_buff_write( &my_buffer, i);
}
printf("Capacity: %d Count: %d\n", my_buffer.capacity, (int)my_buffer.count);
cleanup_c_buff( my_buffer );
return 0;
}
void *c_buff_init( Circular_buffer *buffer, int length )
{
buffer->item_size = sizeof(int);
buffer->buffer = malloc( length * buffer->item_size );
buffer->buffer_end = buffer->buffer + buffer->capacity * buffer->item_size;
buffer->capacity = length;
buffer->count = 0;
buffer->head = buffer;
buffer->tail = buffer;
}
void c_buff_write( Circular_buffer *buffer, const int data)
{
if (buffer->count == buffer->capacity) {
printf( "Your buffer is full\n" );
exit(0);
}
printf("Buffer Capacity: %d Buffer Count %d\n", buffer->capacity, buffer->count);
memcpy( buffer->head, &data, buffer->item_size); // memcpy args = (dest, src, size)
buffer->head = (char*)buffer->head + buffer->item_size;
if (buffer->head == buffer->buffer_end) // If head has reached end of buffer
buffer->head = buffer->buffer; // Set head to start of buffer
buffer->count++;
}
When this program runs, it produces the expected output up until it tries to add the fifth element (heh), where it seems to all of a sudden write over my capacity value.
What gives?
You're using the same name, buffer
, for two different things. One is for the circular buffer, and the other is for the storage that you create via malloc
. Look at where you're setting buffer->head
and buffer->tail
. You're setting them to the structure itself, so you're going to overwrite it. You need to set them to the storage that you create via malloc
.