我正在尝试实现一个用于记录消息的循环缓冲区。我已经实现了一个相当基本的解决方案,它似乎可以工作,但我对推送在实际情况下应该如何工作感到困惑。头部应该覆盖尾部吗?如果是,我们是否修改尾部以反映它指向下一个最旧的日志?
/******************************************************************************
Online C Compiler.
Code, Compile, Run and Debug C program online.
在这个编辑器中编写代码,然后按";运行";按钮编译并执行。
*******************************************************************************/
/******************************************************************************
Online C Compiler.
Code, Compile, Run and Debug C program online.
在这个编辑器中编写代码,然后按";运行";按钮编译并执行。
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#define LOG_SIZE 10
typedef struct{
char *buffer[LOG_SIZE];
int16_t head;
int16_t tail;
int16_t count;
volatile bool full_status;
volatile bool empty_status;
}circbuff;
pthread_mutex_t circMutex;
void circbuff_reset(circbuff *circ_b)
{
circ_b->head = 0;
circ_b->tail =0;
circ_b->full_status = false;
circ_b->count =0;
circ_b->empty_status = false;
}
circbuff * circbuff_init ()
{
circbuff *my_circ_buff = (circbuff *) malloc(sizeof(circbuff));
circbuff_reset(my_circ_buff);
return (my_circ_buff);
}
void push(circbuff *circ_b, char* message)
{
pthread_mutex_lock(&circMutex);
if (!circ_b->full_status)
{
//circ_b->buffer[circ_b->head] = (char*)malloc(strlen(message)+1);
circ_b->buffer[circ_b->head] = strdup(message);
//printf ("Value inserted at position %d is %s and count %drn", circ_b->head, circ_b->buffer[circ_b->head],circ_b->count);
circ_b->head = (circ_b->head + 1) % LOG_SIZE;
if(circ_b->head==circ_b->tail)
circ_b->full_status=true;
circ_b->empty_status=false;
circ_b->count++ ;
}
else //can be changed to overwrite
{
free(circ_b->buffer[circ_b->head]);
circ_b->buffer[circ_b->head] = strdup(message);
//printf ("Value inserted at position %d is %s and count %drn", circ_b->head, circ_b->buffer[circ_b->head],circ_b->count);
circ_b->head = (circ_b->head + 1) % LOG_SIZE;
circ_b->tail = (circ_b->tail + 1) % LOG_SIZE;
if(circ_b->head==circ_b->tail)
circ_b->full_status=true;
circ_b->empty_status=false;
//printf("Cant push logsn");
}
pthread_mutex_unlock(&circMutex);
}
char* pop(circbuff *circ_b)
{
pthread_mutex_lock(&circMutex);
if (!circ_b->empty_status)
{
//printf ("Value read at position %d is %s and count %drn", circ_b->tail, circ_b->buffer[circ_b->tail],circ_b->count);
char* pop_value = circ_b->buffer[circ_b->tail]; //-->free after this?
circ_b->tail = (circ_b->tail + 1) % LOG_SIZE;
if(circ_b->head==circ_b->tail)
circ_b->empty_status=true;
circ_b->count--;
circ_b->full_status=false;
return pop_value;
}
else
return "Empty Buffer";
pthread_mutex_unlock(&circMutex);
}
int main()
{
pthread_mutex_init(&circMutex,NULL);
circbuff* myBuffer = circbuff_init();
char buff[20];
scanf("%s", buff);
push(myBuffer, buff);
scanf("%s", buff);
push(myBuffer, buff);
char *tmp;
for(int i = 0 ;i < 2; i++)
{
tmp = pop(myBuffer);
printf("%s-poppedn",tmp);
free(tmp);
}
pthread_mutex_destroy(&circMutex);
}
这段代码非常糟糕。
circ_b->buffer[circ_b->head] = (char*)malloc(strlen(message)+1);
circ_b->buffer[circ_b->head] = message;
您似乎认为第二行会将消息复制到您刚刚修改过的空间中。它不会;你所做的只是泄露你刚刚分配的内存。您只需将malloc返回的指针替换为消息指针。
使用strdup
,它将为您进行malloc和复制。
其次,当圆圈满了时,您需要释放旧节点的消息,并分配一个新节点。
你能在Linux桌面上运行这段代码吗?如果是这样的话,在Valgrind下运行它,它会揭露你所有的漏洞。
这些"挥发物"也毫无意义。
为了表明当前代码不起作用,我制作了一个不同的主
int main(){
circbuff* myBuffer = circbuff_init(10);
char buff[20];
scanf("%s", buff);
push(myBuffer, buff);
scanf("%s", buff);
push(myBuffer, buff);
for(int i = 0 ;i < 2; i++)
printf("%s-poppedn",pop(myBuffer));
}
运行它并获得
hello1
Value inserted at position 0 is hello1
hello2
Value inserted at position 1 is hello2
Value read at position 0 is hello2 <<<<======
hello2-popped
Value read at position 1 is hello2
hello2-popped
你看你两次打出了hello2
这是valgrims输出
==4752== HEAP SUMMARY:
==4752== in use at exit: 94 bytes in 3 blocks
==4752== total heap usage: 5 allocs, 2 frees, 2,142 bytes allocated
==4752==
==4752== 3 bytes in 1 blocks are definitely lost in loss record 1 of 3
==4752== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4752== by 0x109282: push (in /home/pm100/ut/a.out)
==4752== by 0x10971B: main (in /home/pm100/ut/a.out)
==4752==
==4752== 3 bytes in 1 blocks are definitely lost in loss record 2 of 3
==4752== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4752== by 0x109282: push (in /home/pm100/ut/a.out)
==4752== by 0x109746: main (in /home/pm100/ut/a.out)
==4752==
==4752== 88 bytes in 1 blocks are definitely lost in loss record 3 of 3
==4752== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4752== by 0x109221: circbuff_init (in /home/pm100/ut/a.out)
==4752== by 0x1096EC: main (in /home/pm100/ut/a.out)
==4752==
==4752== LEAK SUMMARY:
==4752== definitely lost: 94 bytes in 3 blocks
==4752== indirectly lost: 0 bytes in 0 blocks
==4752== possibly lost: 0 bytes in 0 blocks
==4752== still reachable: 0 bytes in 0 blocks
==4752== suppressed: 0 bytes in 0 blocks
==4752==
==4752== For lists of detected and suppressed errors, rerun with: -s