检测到glibc *** free():指针无效

时间:2012-04-24 03:04:23

标签: c pointers free glibc

我对这段代码有以下问题。有人可以帮忙吗?

注意: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);

调用dequeue

2 个答案:

答案 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));

如果不能解决问题,您可以编辑问题以包含:

  1. 队列结构的定义
  2. 您如何致电DequeueSynchronous(或*Q成为**Q

  3. 无关紧要,请注意您还有一个错误,当列表在出列后变空时,您不会清除尾部。我怀疑你可能需要写:

    (*Q)->Head = ((*Q)->Head)->NextItem;
    if ((*Q)->Head == NULL) (*Q)->Tail = NULL;
    

    如果队列中没有头部,这将清除尾部。

答案 1 :(得分:1)

据我们所知,这没有任何本质上的错误。但问题必须是tmp(换句话说,在进入函数时(*Q)->Head)不是指向由malloc()分配的块的指针。如果它是以任何其他方式分配的 - 或者如果它是指向块中间的指针而不是开头 - 那么你就不能用free()释放它。

它也有可能已经被释放;也许你的多个线程导致它被释放不止一次。