我正在使用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,则指针指向缓冲区的末尾
如果有人知道为什么会发生这种情况,以及如何解决,请帮帮我..
提前致谢
答案 0 :(得分:2)
我认为您需要删除* sz
。 (而且我认为你不需要演员。)
cb->buffer_end = cb->buffer + (capacity-1);
指针运算自动计算指向的类型的大小。
我还应该指出boost::circular_buffer。
答案 1 :(得分:2)
似乎你误解了指针算法
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-isms”(typedeffing结构,使用struct XXX var;
- 尽管它有typedeffed等),并且代码通常是纯粹设计的C风格(没有利用C ++的最大优势,使用RAII进行自动资源管理)。
我还要指出clock()
几乎没有给你一个日期:)
答案 2 :(得分:1)
你假设指针是4字节宽。在所有平台(x86_64)上可能并非如此。因此,memcpy()应该使用sizeof运算符。 “end = buffer +(capacity - 1)* size”似乎还有另一个错误。与cb_push_back()一起使用时,你要分配一个元素太多(或者你没有使用ringbuffer的最后一个元素).cb_count会增加在每个push_back中,所以你的缓冲区可以拥有比元素更多的“计数”。
答案 3 :(得分:0)
如果要用C ++编写代码,至少要使用STL。试试std::list