我试图创建队列作为双void指针。pollQueue
函数用于处理队列并返回队列元素指针dest
。
我已经设法把问题简化成这样:
#include <stdio.h>
#include <stdlib.h>
void **queue;
int queueSize = 0;
int pollQueue(void **dest, int *processPlace);
int processQueue();
int main(void){
int data = 5;
queue = malloc(sizeof(void *));
queueSize++;
*queue = &data;
processQueue();
free(queue);
return 0;
}
int processQueue(){
void *queueElement = NULL;
int processPlace = -1;
while(pollQueue(&queueElement, &processPlace) == 0)
{
//do something with queue element
};
return 0;
}
int pollQueue(void **dest, int *processPlace){
static int processNumber = 0;
//void *cur = queue[processNumber];
void *cur = *(queue + processNumber); //0 here
printf("process number: %in", processNumber);
//if end of the queue reached retun 0 and prepare for next poll
if(!cur || queueSize == processNumber)
{
*processPlace = processNumber;
dest = NULL;
processNumber = 0;
return 1;
}
*processPlace = processNumber;
*dest = cur;
processNumber++;
return 0;
}
当我通过valgrind运行这段代码时,我得到了这个:
==14570== Memcheck, a memory error detector
==14570== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14570== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==14570== Command: ./test
==14570==
process number: 0
==14570== Invalid read of size 8
==14570== at 0x1092B4: pollQueue (in /home/jan/Documents/programing/c_c++/population/sim/test/test)
==14570== by 0x10926A: processQueue (in /home/jan/Documents/programing/c_c++/population/sim/test/test)
==14570== by 0x109202: main (in /home/jan/Documents/programing/c_c++/population/sim/test/test)
==14570== Address 0x4a96048 is 0 bytes after a block of size 8 alloc'd
==14570== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14570== by 0x1091D4: main (in /home/jan/Documents/programing/c_c++/population/sim/test/test)
==14570==
process number: 1
==14570==
==14570== HEAP SUMMARY:
==14570== in use at exit: 0 bytes in 0 blocks
==14570== total heap usage: 2 allocs, 2 frees, 1,032 bytes allocated
==14570==
==14570== All heap blocks were freed -- no leaks are possible
==14570==
==14570== For lists of detected and suppressed errors, rerun with: -s
==14570== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
我不明白是什么导致错误,我发现它更奇怪,当我显式地设置0来模拟函数第一次调用时应该发生的事情。错误消失。
int pollQueue(void **dest, int *processPlace){
static int processNumber = 0;
//void *cur = queue[processNumber];
void *cur = *(queue + 0); //0 here
printf("process number: %in", processNumber);
//if end of the queue reached retun 0 and prepare for next poll
if(!cur || queueSize == processNumber)
{
*processPlace = processNumber;
dest = NULL;
processNumber = 0;
return 1;
}
*processPlace = processNumber;
*dest = cur;
processNumber++;
return 0;
}
我不能解释为什么使用变量会导致无效读取,但是当隐式地给出值时,它工作得很好。有人能解释一下吗?
static
函数变量的全部意义在于它们在调用之间保持其值。
第一次调用processQueue
时,processNumber
以0
开始。在函数退出前,processNumber
被加为1
。
第二次调用processQueue
时,processNumber
开始为1
。由于queue
只有一个元素,访问*(queue + processNumber)
也就是queue[processNumber]
会导致未定义的行为。
valgrind
正在捕获这个严重的错误。