我对这段代码有以下问题。有人可以帮忙吗?
注意:QueueItem是在不同的线程上创建的。
WorkItem * Dequeue(Queue ** Q)
{
if(QueueIsEmpty(*Q)) return NULL;
QueueItem * tmp = (*Q)->Head;
(*Q)->Head = ((*Q)->Head)->NextItem;
WorkItem * retval = tmp->workItem;
free(tmp); //Generates glibc detected *** free(): invalid pointer
return retval;
}
edit当多个线程正在运行时,此函数在访问时受到保护。
WorkItem * DequeueSynchronous(Queue ** Q)
{
WorkItem * retval;
pthread_mutex_lock((*Q)->QueMutex);
retval = Dequeue (Q);
pthread_mutex_unlock((*Q)->QueMutex);
return retval;
}
(* Q) - >头部;被分配了我的malloc。
Queue * Queue_Init(pthread_mutex_t * mutex)
{
Queue * retval = (Queue *)malloc(sizeof(Queue *));
retval->Head = retval->Tail =NULL;
retval->QueMutex = mutex;
return retval;
}
void Enqueue (Queue * Q, WorkItem * WI)
{
if(!Q)return;
QueueItem * QI = (QueueItem *) malloc(sizeof(QueueItem *));
QI->workItem = WI;
QI->NextItem = NULL;
if(QueueIsEmpty(Q))
{
Q->Head = Q->Tail = QI;
return;
}
Q->Tail->NextItem = QI;
Q->Tail = QI;
}
void EnqueueSynchronous (Queue * Q, WorkItem * WI)
{
pthread_mutex_lock(Q->QueMutex);
Enqueue (Q, WI);
pthread_mutex_unlock(Q->QueMutex);
}
还要感谢输入,我会看看valgrind。
编辑2
typedef struct {
char ** FileNames;
int ** Results;
int NumOfItems;
}WorkItem;
typedef struct QI{
WorkItem * workItem;
struct QI * NextItem;
}QueueItem;
typedef struct {
QueueItem * Head, * Tail;
pthread_mutex_t * QueMutex;
}Queue;
叫出队 - Dequeue(&WorkQue)
调用Dequeue
的所有主题都被赋予&WorkQue
作为其args的一部分;
typedef struct{
int ThreadID;
WorkItem * workItem;
char ** keywordsArray;
int nKeywords;
Queue ** WorkQueue, ** WorkCompletedQ;
}ThreadArgs;
pthread_t threads[NTHREADS];
ThreadArgs threadArgs[NTHREADS];
for(i=0;i<NTHREADS;i++)
{
threadArgs[i].ThreadID=i;
threadArgs[i].workItem = Dequeue(&WorkQue);
threadArgs[i].WorkQueue = &WorkQue;
threadArgs[i].WorkCompletedQ = &WorkCompletedQ;
threadArgs[i].nKeywords=_kwlist->length;
threadArgs[i].keywordsArray = ListToArray(*_kwlist);
}
for(i=0;i<NTHREADS;i++)
{
pthread_create(&threads[i], NULL, WorkerThread,(void *)&(threadArgs[i]));
}
每个线程使用myWork = DequeueSynchronous(myThreadArgs->WorkQueue);
答案 0 :(得分:3)
查看更新的代码,我认为由于以下这些问题导致内存损坏:
Queue * retval = (Queue *)malloc(sizeof(Queue *));
请注意,您只需为该指针分配足够的指针 - 您应该写一下:
Queue * retval = (Queue *)malloc(sizeof(Queue)); // version one
或更好:
Queue * retval = (Queue *)malloc(sizeof(*retval)); // version two
第二个版本更好,因为它对retval
类型的更改很有用。
这两行都说“为队列分配足够的空间,并将队列指针retval
设置为指向它”。您之前的行说“为队列指针分配足够的空间,并将队列指针retval
设置为指向它”。旧版本导致分配不足(因为结构几乎肯定比指针大)。
然后,当您分配到队列结构中超出实际分配空间的部分时,会标记内存的其他部分。我怀疑这会导致你标记一些malloc()
的内部控制数据,这是导致以后无效释放的原因。您需要将所有malloc()
调用更改为malloc结构的大小而不是指针的大小。
请注意,您还应该not cast the result of malloc。在我看来,你的最终malloc()
陈述应如下所示:
Queue * retval = malloc(sizeof(*retval));
如果不能解决问题,您可以编辑问题以包含:
DequeueSynchronous
(或*Q
成为**Q
)无关紧要,请注意您还有一个错误,当列表在出列后变空时,您不会清除尾部。我怀疑你可能需要写:
(*Q)->Head = ((*Q)->Head)->NextItem;
if ((*Q)->Head == NULL) (*Q)->Tail = NULL;
如果队列中没有头部,这将清除尾部。
答案 1 :(得分:1)
据我们所知,这没有任何本质上的错误。但问题必须是tmp
(换句话说,在进入函数时(*Q)->Head
)不是指向由malloc()
分配的块的指针。如果它是以任何其他方式分配的 - 或者如果它是指向块中间的指针而不是开头 - 那么你就不能用free()
释放它。
它也有可能已经被释放;也许你的多个线程导致它被释放不止一次。