在 C 中实现循环缓冲区,得到未定义的行为
Implementing Circular Buffer in C, getting undefined behavior
我回来了,看来我还没有完全弄清楚 C 中的内存管理。在尝试设计事件队列时,我决定构建一个循环缓冲区作为练习。经过一些研究后,我尝试在我在 SO 上看到的以下实现之后对其进行建模: .
我决定稍微简化一下,而不是为任何数据类型构建一个缓冲区,我只想为整数构建一个缓冲区。在大多数情况下,我能够遵循逻辑,尽管我不明白作者为什么偶尔会将值转换为 (char *)。我已经尝试过使用和不使用 (char *) 强制转换的程序,但在这两种情况下它都会产生相同的错误输出。
一旦我写入超过某个点,缓冲区中不应更改的值就会受到影响,我认为这与我为缓冲区分配内存的方式有关。看起来程序正在写入我在我的结构中分配的缓冲区,并且正在覆盖本来应该是静态的值。我这辈子都想不出如何解决这个错误,但我暗暗怀疑这是我设法忽略的非常明显的事情。
这是我的代码:
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++;
}
当这个程序运行时,它会产生预期的输出,直到它尝试添加第五个元素(呵呵),它似乎突然覆盖了我的容量值。
什么给了?
您使用相同的名称 buffer
来表示两个不同的事物。一个用于循环缓冲区,另一个用于您通过 malloc
创建的存储。查看您设置 buffer->head
和 buffer->tail
的位置。您将它们设置为结构本身,因此您将覆盖它。您需要将它们设置为您通过 malloc
.
创建的存储
我回来了,看来我还没有完全弄清楚 C 中的内存管理。在尝试设计事件队列时,我决定构建一个循环缓冲区作为练习。经过一些研究后,我尝试在我在 SO 上看到的以下实现之后对其进行建模: .
我决定稍微简化一下,而不是为任何数据类型构建一个缓冲区,我只想为整数构建一个缓冲区。在大多数情况下,我能够遵循逻辑,尽管我不明白作者为什么偶尔会将值转换为 (char *)。我已经尝试过使用和不使用 (char *) 强制转换的程序,但在这两种情况下它都会产生相同的错误输出。
一旦我写入超过某个点,缓冲区中不应更改的值就会受到影响,我认为这与我为缓冲区分配内存的方式有关。看起来程序正在写入我在我的结构中分配的缓冲区,并且正在覆盖本来应该是静态的值。我这辈子都想不出如何解决这个错误,但我暗暗怀疑这是我设法忽略的非常明显的事情。
这是我的代码:
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++;
}
当这个程序运行时,它会产生预期的输出,直到它尝试添加第五个元素(呵呵),它似乎突然覆盖了我的容量值。
什么给了?
您使用相同的名称 buffer
来表示两个不同的事物。一个用于循环缓冲区,另一个用于您通过 malloc
创建的存储。查看您设置 buffer->head
和 buffer->tail
的位置。您将它们设置为结构本身,因此您将覆盖它。您需要将它们设置为您通过 malloc
.