我正在使用 Visual C++。
我正在尝试实现一个循环缓冲区,这个 CB 必须处理特定类型的数据......事实上,它是一个结构数据,我们有一些原始数据以 char 类型和日期存储与该数据相关联...这已使用结构实现。
这里是更多细节的代码:
#include <stdio.h>
#include <time.h>
#include <windows.h>
//data=date_label+raw_data
typedef struct DataFragment
{
char data[4];
clock_t date;
}DataFragment;
typedef struct CircularBuffer
{
DataFragment *buffer; // data buffer
DataFragment *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
DataFragment *head; // pointer to head
DataFragment *tail; // pointer to tail
} CircularBuffer;
void cb_init(struct CircularBuffer *cb, size_t capacity, size_t sz)
{
if((cb->buffer = (DataFragment*) malloc(capacity * sz))!=NULL)
puts("success alocation");
//if(cb->buffer == NULL)
//handle error
cb->buffer_end = (DataFragment *)cb->buffer + (capacity-1)*sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}
void cb_free(struct CircularBuffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}
void cb_push_back(struct CircularBuffer *cb, const DataFragment *item)
{
//if(cb->count == cb->capacity)
//handle error when it's full
memcpy(cb->head->data, item->data,4);
cb->head->date=item->date;
cb->head = (DataFragment*)cb->head + cb->sz;
if(cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
}
void cb_pop_front(struct CircularBuffer *cb, DataFragment *item)
{
//if(cb->count == 0)
//handle error
memcpy(item->data, cb->tail->data,4);
item->date=cb->tail->date;
cb->tail = (DataFragment*)cb->tail + cb->sz;
if(cb->tail == cb->buffer_end)
cb->tail = cb->buffer;
cb->count--;
}
int main(int argc, char *argv[])
{
struct CircularBuffer pbuf;
pbuf.buffer=NULL;
pbuf.buffer_end=NULL;
pbuf.capacity=0;
pbuf.count=0;
pbuf.head=NULL;
pbuf.sz=0;
pbuf.tail=NULL;
struct CircularBuffer *buf= &pbuf;
size_t sizz = sizeof(DataFragment);
//initialisation of the circlar buffer to a total bytes
//of capacity*sizz=100*sizeof(struct DataFragment)
cb_init(buf,100,sizz);
//temporary container of data
DataFragment temp,temp2;
for(int i=0;i<4;i++)
temp.data[i]='k';
for(int i=0;i<4;i++)
temp2.data[i]='o';
//pushing temporary buffer to the CB...40*2=80<capacity of the CB
for(int i=0;i<40;i++)
{
Sleep(20);
temp.date=clock();
cb_push_back(buf,&temp);
Sleep(10);
temp2.date=clock();
cb_push_back(buf,&temp2);
}
DataFragment temp3;
for(int i=0;i<20;i++)
{
cb_pop_front(buf,&temp3);
printf("%d\n", temp3.data); //print integers....no need of end caracter
}
cb_free(buf);
return 0;
}
当我编译代码时,一切都很好,但是当我调试时,我注意到 buffer_end 指针有问题,它说 bad_pointer ....如果容量大于 56 就会发生这种情况......我没有知道为什么指针不能指向缓冲区的末尾。但是如果容量小于 56,则指针恰好指向缓冲区的末尾
如果有人知道为什么会这样,以及如何解决它,请帮助我..
提前致谢
最佳答案
看来你对指针运算有误解
cb->buffer_end = (DataFragment *)cb->buffer + (capacity-1)*sz;
cb->head = (DataFragment*)cb->head + cb->sz;
cb->tail = (DataFragment*)cb->tail + cb->sz;
指针算法已经考虑了底层类型的大小。你真正需要的是
++cb->head;
++cb->tail;
如果想法是绕过 sizeof(DataFragment)
- 可能为一个项目分配比结构大小更多的存储空间 - 出于某些邪恶的目的 - 你需要首先将指针转换为一个 char*
(因为 sizeof(char) == 1
)。
cb->tail = (DataFragment*)((char*)cb->tail + cb->sz);
在设计方面,该结构似乎有太多成员:buffer_end
和 capacity
相互重复(给定一个,您总能找到另一个),并且 sz
成员不是必需的(它应该始终是 sizeof(DataFragment)
。
此外,我相信你可以只分配结构
*(cb->head) = *item;
似乎完全没有必要进行强制转换(可能是由于对指针运算的误解):
cb->buffer_end = (DataFragment *)cb->buffer + (capacity-1)*sz;
如果它应该是 C++,那么它包含很多“C 主义”(typedeffing structs,使用 struct XXX var;
- 尽管它有 typedeffed,等等)和代码通常以纯 C 风格设计(没有利用 C++ 的最大优势,使用 RAII 进行自动资源管理)。
我还可以指出 clock()
很难给你一个date :)
关于c - 循环缓冲区的结束指针问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5065318/