从结构“无效的读/写"中的指针获取数据. [英] Getting data from pointer in struct "Invalid read/write"
问题描述
我正在尝试在数组中实现循环缓冲区.我将数据保持在结构中,并通过push,pop等几种方法对其进行管理.该程序或多或少地具有功能并按预期运行,但是在valgrind测试中遇到了错误.而且我无法找出我的代码出了什么问题.尽管似乎通过指针在我的结构中管理数据是关键问题.如果有人能指出正确的方向,我将非常感激,因为此时我真的迷路了.
I am trying to do a implementation of circular buffer in array. I keep my data in structure and manage it by few methods as push, pop, etc. The program is more or less functional and behave as expected, however I run into errors in my valgrind test. And I am not capable of finding out what is wrong with my code. Although it seems like managing data via pointers in my struct is the crucial problem. I would be very grateful if anyone could point me in the right direction coz I am really lost at this point.
这是我的结构的样子:
typedef struct queue_t{
int* data;
int* end;
int* head;
int* tail;
int max_length;
int cur_length;
} queue_t;
以下是我管理缓冲区操作的方法:
(注释代码产生的错误与memcpy几乎相同)
Here are my methods to manage buffer operations:
(Commented code produces pretty much the same errors as memcpy)
int* increase(int* point, queue_t* queue){
if(point != queue->end){
point = point + sizeof(int*);
return point;
}else{
return queue->data;
}
}
queue_t* create_queue(int capacity){
queue_t* fifo;
fifo = malloc(sizeof(queue_t));
fifo->data = malloc((capacity) * sizeof(int*));
fifo->end = fifo->data + (capacity*sizeof(int*));
fifo->head = fifo->data;
fifo->tail = fifo->data;
fifo->cur_length = 0;
fifo->max_length = capacity;
return fifo;
}
void delete_queue(queue_t *queue){
free(queue->data);
free(queue);
}
bool push_to_queue(queue_t *queue, void *data){
int *temp = (int*) data;
//*(queue->tail) = *temp;
memcpy(queue->tail, temp, sizeof(int));
free(data);
if(queue->max_length != queue->cur_length){
queue->cur_length++;
}
queue->tail = increase(queue->tail, queue);
if(queue->tail == queue->head){
queue->head = increase(queue->head, queue);
}
return true;
}
void* pop_from_queue(queue_t *queue){
if(queue->cur_length == 0){
return NULL;
}
int *item = malloc(sizeof(int*));
//*item = *(queue->head);
memcpy(item, queue->head, sizeof(int));
queue->head = increase(queue->head, queue);
queue->cur_length--;
return item;
}
这是我测试提到的缓冲区操作的功能的主要方法:
(queue.h是定义我的函数的地方)
This is my main method to test funcionality of mentioned buffer operations:
(queue.h is where my functions are defined)
#include "queue.h"
void print_int(void* p){
if(p != NULL){
printf("%d\n", *((int*)p));
} else {
printf("NULL\n");
}
}
int main(){
int n = 2;
int max = 10;
queue_t *q;
q = create_queue(n);
for(int i = 0; i<max;i++){
int* p = malloc(sizeof(int));
*p = i;
if(!push_to_queue(q, (void*)p)){
free(p);
exit(101);
}
}
for(int i = 0;i<max;i++){
void* p = pop_from_queue(q);
print_int(p);
free(p);
}
delete_queue(q);
return 0;
}
最后这是我的valgrind输出:
==20293== HEAP SUMMARY:
==20293== in use at exit: 0 bytes in 0 blocks
==20293== total heap usage: 15 allocs, 15 frees, 1,136 bytes allocated
==20293==
==20293== All heap blocks were freed -- no leaks are possible
==20293==
==20293== ERROR SUMMARY: 7 errors from 2 contexts (suppressed: 0 from 0)
==20293==
==20293== 1 errors in context 1 of 2:
==20293== Invalid read of size 4
==20293== at 0x40097C: pop_from_queue (queue.c:72)
==20293== by 0x400713: main (main.c:30)
==20293== Address 0x52030f0 is 16 bytes before a block of size 4 free'd
==20293== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20293== by 0x4008B8: push_to_queue (queue.c:51)
==20293== by 0x4006D5: main (main.c:23)
==20293== Block was alloc'd at
==20293== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20293== by 0x4006B5: main (main.c:21)
==20293==
==20293==
==20293== 6 errors in context 2 of 2:
==20293== Invalid write of size 4
==20293== at 0x4008AB: push_to_queue (queue.c:50)
==20293== by 0x4006D5: main (main.c:23)
==20293== Address 0x52030d0 is 16 bytes after a block of size 16 alloc'd
==20293== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20293== by 0x4007FB: create_queue (queue.c:33)
==20293== by 0x40069E: main (main.c:18)
==20293==
==20293== ERROR SUMMARY: 7 errors from 2 contexts (suppressed: 0 from 0)
代码指向的行是:
72: memcpy(item, queue->head, sizeof(int));
50: memcpy(queue->tail, temp, sizeof(int));
非常感谢,我希望有人能够告诉我,我在这里做的不好的做法是什么:/
Thanks a lot in advance, I hope someone will be able to show me, what is that bad practice I am doing here :/
推荐答案
这有一些问题.首先,您不应该将数据转换为int *,因为它可以是指向任何内容的指针.在您的struct声明中,数据数组和所有其他指针都应声明为void **,因为它指向存储在数组中的void *类型.您实际上根本不需要memcpy.您只需按以下方式分配它:*(queue->tail) = data;
其中数据的类型为void *.我认为,更清晰的方法是将头和尾存储为整数(作为相对于数组的索引)-然后您可以执行此操作:queue->data[queue->tail] = data;
无需手动处理指针.
There's a few problems with this. First, you shouldn't cast the data to an int* because it can be a pointer to anything. In your struct declaration, the data array and all the other pointers should be declared as void** since it points to this void* type that is stored in the array. You don't actually need memcpy at all. You just assign it like this: *(queue->tail) = data;
where data is of type void*. In my opinion, a more clear way would be to just store the head and tail as integers (as an index relative to the array) - then you could do this: queue->data[queue->tail] = data;
without having to deal with the pointers manually.
现在您在这些行上正在做什么:
Right now what you're doing on these lines:
int *item = malloc(sizeof(int*));
memcpy(item, queue->head, sizeof(int));
正在分配一些永远不会释放的内存,但更重要的是,您实际上甚至没有返回存储在queue-> head中的值.您将返回刚刚为该项分配的内存块的地址.要获得该值,您必须用星号将其取消引用,例如:return *item;
同样,您真正想要的只是一个简单的赋值:void *item = *(queue->head);
is allocating some memory that never gets freed but more importantly, you're not actually even returning the value that was stored in queue->head. You're returning the address of the block of memory you just allocated for the item. To get the value, you would have to dereference it with a star, as in: return *item;
Again, what you really want though is a simple assignment: void *item = *(queue->head);
这篇关于从结构“无效的读/写"中的指针获取数据.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!