C 通用环形缓冲区
我已经实现了一个通用的环形缓冲区,但是我遇到了一些奇怪的结果。首先我成功地推送了15个整数,但是当我试图打印到缓冲区的内容时,它打印出了一些错误的元素 首先我为10个整数分配内存。然后我尝试推15,然后调整缓冲区的大小。也许调整缓冲区的大小会以某种方式破坏它,因为没有它,它工作得很好 RingBuffer.cC 通用环形缓冲区,c,C,我已经实现了一个通用的环形缓冲区,但是我遇到了一些奇怪的结果。首先我成功地推送了15个整数,但是当我试图打印到缓冲区的内容时,它打印出了一些错误的元素 首先我为10个整数分配内存。然后我尝试推15,然后调整缓冲区的大小。也许调整缓冲区的大小会以某种方式破坏它,因为没有它,它工作得很好 RingBuffer.c #include<stdlib.h> #include<string.h> #include <stdio.h> #include"RingB
#include<stdlib.h>
#include<string.h>
#include <stdio.h>
#include"RingBuffer.h"
unsigned char RingInit(RingBuffer* buffer, int elemLen, int elemSize, void (*fn)(void*))
{
buffer->dataLen = elemLen;
buffer->dataSize = elemSize;
if( (buffer->data = malloc( buffer->dataSize * buffer->dataLen )) == NULL){
return 1;
}
buffer->head = 0;
buffer->tail = 0;
buffer->elemCount = 0;
buffer->freeFn = fn;
buffer->doResize = 1;
buffer->resizeBy = 2;
return 0;
}
unsigned char RingPush(RingBuffer* buffer, void* elem)
{
if(RingIsFull(buffer)){
if(!buffer->doResize || RingResize(buffer)){
return 1;
}
}
memcpy((buffer->data + (buffer->head*buffer->dataSize)), elem, buffer->dataSize);
buffer->head = (buffer->head + 1) % buffer->dataLen;
buffer->elemCount++;
return 0;
}
unsigned char RingRead(RingBuffer* buffer, void* elem)
{
if(!RingIsEmpty(buffer)){
memcpy(elem, (buffer->data + (buffer->tail*buffer->dataSize)), buffer->dataSize);
buffer->tail = (buffer->tail + 1) % buffer->dataLen;
buffer->elemCount--;
return 0;
}
return 1;
}
unsigned char RingIsEmpty(RingBuffer* buffer)
{
return (buffer->elemCount == 0);
}
unsigned char RingIsFull(RingBuffer* buffer)
{
return (buffer->elemCount == buffer->dataLen);
}
void RingFree(RingBuffer* buffer)
{
buffer->freeFn(buffer->data);
}
unsigned char RingResize(RingBuffer* buffer)
{
unsigned char* newMemory = NULL;
if ( (newMemory = realloc(buffer->data, buffer->dataLen + (buffer->resizeBy * buffer->dataSize))) == NULL){
return 1;
}
buffer->data = newMemory;
buffer->dataLen += buffer->resizeBy;
buffer->head = buffer->elemCount;
return 0;
}
#include<stdlib.h>
#include<string.h>
#include <stdio.h>
#include"RingBuffer.h"
#define ARRAY_LENGTH(a) sizeof(a)/sizeof(a[0])
void freeInt(void* data)
{
free(data);
}
int main(void)
{
RingBuffer Ring;
int buf[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int i = 0;
if(RingInit(&Ring, ARRAY_LENGTH(buf)-5, sizeof(int), freeInt) == 0){
printf("\nRING INIT OK");
}
else{
printf("\nRING INIT FAIL");
RingFree(&Ring);
return 0;
}
Ring.doResize = 1;
for(i = 0 ; i < ARRAY_LENGTH(buf) ; i++){
if(RingPush(&Ring, &buf[i])){
printf("\nRING PUSH FAIL");
RingFree(&Ring);
return 0;
}
printf("\nRING PUSH OK->%d", buf[i]);
printf(" %d", ((int*)(Ring.data))[i]);
}
printf("\n");
for(i = 0 ; i < ARRAY_LENGTH(buf); i++){
printf(" %d", ((int*)(Ring.data))[i]);
}
memset(buf, 0, sizeof(buf));
printf("\nLOAD ZEROS:");
for(i = 0 ; i < ARRAY_LENGTH(buf); i++){
printf(" %d", buf[i]);
}
i = 0;
while(!RingIsEmpty(&Ring)){
if(RingRead(&Ring, &buf[i])){
printf("\nRING READ FAIL");
RingFree(&Ring);
return 0;
}
printf("\nRING READ OK->%d", buf[i]);
i++;
}
getchar();
RingFree(&Ring);
return 0;
}
Test.c
#include<stdlib.h>
#include<string.h>
#include <stdio.h>
#include"RingBuffer.h"
unsigned char RingInit(RingBuffer* buffer, int elemLen, int elemSize, void (*fn)(void*))
{
buffer->dataLen = elemLen;
buffer->dataSize = elemSize;
if( (buffer->data = malloc( buffer->dataSize * buffer->dataLen )) == NULL){
return 1;
}
buffer->head = 0;
buffer->tail = 0;
buffer->elemCount = 0;
buffer->freeFn = fn;
buffer->doResize = 1;
buffer->resizeBy = 2;
return 0;
}
unsigned char RingPush(RingBuffer* buffer, void* elem)
{
if(RingIsFull(buffer)){
if(!buffer->doResize || RingResize(buffer)){
return 1;
}
}
memcpy((buffer->data + (buffer->head*buffer->dataSize)), elem, buffer->dataSize);
buffer->head = (buffer->head + 1) % buffer->dataLen;
buffer->elemCount++;
return 0;
}
unsigned char RingRead(RingBuffer* buffer, void* elem)
{
if(!RingIsEmpty(buffer)){
memcpy(elem, (buffer->data + (buffer->tail*buffer->dataSize)), buffer->dataSize);
buffer->tail = (buffer->tail + 1) % buffer->dataLen;
buffer->elemCount--;
return 0;
}
return 1;
}
unsigned char RingIsEmpty(RingBuffer* buffer)
{
return (buffer->elemCount == 0);
}
unsigned char RingIsFull(RingBuffer* buffer)
{
return (buffer->elemCount == buffer->dataLen);
}
void RingFree(RingBuffer* buffer)
{
buffer->freeFn(buffer->data);
}
unsigned char RingResize(RingBuffer* buffer)
{
unsigned char* newMemory = NULL;
if ( (newMemory = realloc(buffer->data, buffer->dataLen + (buffer->resizeBy * buffer->dataSize))) == NULL){
return 1;
}
buffer->data = newMemory;
buffer->dataLen += buffer->resizeBy;
buffer->head = buffer->elemCount;
return 0;
}
#include<stdlib.h>
#include<string.h>
#include <stdio.h>
#include"RingBuffer.h"
#define ARRAY_LENGTH(a) sizeof(a)/sizeof(a[0])
void freeInt(void* data)
{
free(data);
}
int main(void)
{
RingBuffer Ring;
int buf[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int i = 0;
if(RingInit(&Ring, ARRAY_LENGTH(buf)-5, sizeof(int), freeInt) == 0){
printf("\nRING INIT OK");
}
else{
printf("\nRING INIT FAIL");
RingFree(&Ring);
return 0;
}
Ring.doResize = 1;
for(i = 0 ; i < ARRAY_LENGTH(buf) ; i++){
if(RingPush(&Ring, &buf[i])){
printf("\nRING PUSH FAIL");
RingFree(&Ring);
return 0;
}
printf("\nRING PUSH OK->%d", buf[i]);
printf(" %d", ((int*)(Ring.data))[i]);
}
printf("\n");
for(i = 0 ; i < ARRAY_LENGTH(buf); i++){
printf(" %d", ((int*)(Ring.data))[i]);
}
memset(buf, 0, sizeof(buf));
printf("\nLOAD ZEROS:");
for(i = 0 ; i < ARRAY_LENGTH(buf); i++){
printf(" %d", buf[i]);
}
i = 0;
while(!RingIsEmpty(&Ring)){
if(RingRead(&Ring, &buf[i])){
printf("\nRING READ FAIL");
RingFree(&Ring);
return 0;
}
printf("\nRING READ OK->%d", buf[i]);
i++;
}
getchar();
RingFree(&Ring);
return 0;
}
它应该打印数字1-15。它会打印出一些错误的数字。每次我启动程序时,不同的元素都是错误的
编译
gcc Test.c RingBuffer.c
编者版本
gcc(MinGW.org gcc-6.3.0-1)6.3.0
版权所有(C)2016免费软件基金会。
这是自由软件;有关复制条件,请参见源。没有
担保甚至不适用于适销性或特定用途。您将
buffer->dataLen+(buffer->resizeBy*buffer->dataSize)
作为要在函数RingResize
中分配的大小
不幸的是,buffer->dataLen
是元素数,而不是字节数
因此,新分配的缓冲区将没有足够的字节数。
这将导致错误
要分配的大小应该是
buffer->dataSize*(buffer->dataLen+buffer->resizeBy)
您传递的buffer->dataLen+(buffer->resizeBy*buffer->dataSize)
作为要在函数RingResize
中分配的大小
不幸的是,buffer->dataLen
是元素数,而不是字节数
因此,新分配的缓冲区将没有足够的字节数。
这将导致错误
要分配的大小应该是
buffer->dataSize*(buffer->dataLen+buffer->resizeBy)
地址Sanitizer在打印前检测到堆缓冲区溢出环推确定->10 10
数组长度(buf)-5
@ChristianGibbons故意分配一个较小的缓冲区来测试调整大小功能是否有效请使用size\u t
来调整大小!AddressSanitanizer在打印前检测到堆缓冲区溢出RING PUSH OK->10 10
ARRAY_LENGTH(buf)-5
@ChristianGibbons故意分配一个较小的缓冲区来测试调整大小功能是否工作请使用size_t
来调整大小!