c - 循环缓冲区的结束指针问题

标签 c memory pointers buffer circular-buffer

我正在使用 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_endcapacity 相互重复(给定一个,您总能找到另一个),并且 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/

相关文章:

在 C 中将不存在的 ASCII 字符转换为 int

c - 为什么 32 位和 64 位地址有两种不同的长度?

c - 从 C 中的数组堆栈中弹出 - 将 NULL 分配给 int *

c++ - 在 MPI、C++ 上分配单个堆栈数组

java - 什么可能导致 JVM 崩溃并显示 SIGSEGV "ClassLoaderData::metaspace_non_null()"

c++ - 如何保留一个类的实例列表?

内存可能是问题吗?

c - 有没有办法自动打印 float 到它的小数位数?

c - 汉明码 - 错误检测和纠正

二维字符串数组的 C 内存布局