1

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

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

编辑当多个线程正在运行时,此功能在访问时受到保护。

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 被调用 -Dequeue(&WorkQue) 所有调用的线程Dequeue&WorkQue作为其参数的一部分给出;

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]));
}

每个线程调用 dequeue 使用myWork = DequeueSynchronous(myThreadArgs->WorkQueue);

4

2 回答 2

3

查看您更新的代码,我认为您由于以下几行而出现内存损坏:

Queue * retval = (Queue *)malloc(sizeof(Queue *));

请注意,您只为指向 Queue 的指针分配了足够的空间 - 您应该改为编写:

Queue * retval = (Queue *)malloc(sizeof(Queue)); // version one

或更好:

Queue * retval = (Queue *)malloc(sizeof(*retval)); // version two

第二个版本更好,因为它对retval.

这两行都说“为队列分配足够的空间,并将队列指针设置retval为指向它”。您的上一行说“为队列指针分配足够的空间,并将队列指针设置retval为指向它”。旧版本导致分配不足(因为结构几乎肯定比指针大)。

然后,当您分配超出实际分配空间的 Queue 结构部分时,您会标记内存的其他部分。我怀疑这会导致您标记一些malloc()内部控制数据,这就是后来导致无效免费的原因。您将需要更改所有malloc()调用 malloc 结构的大小而不是指针的大小。

请注意,您也不应该转换 malloc 的结果。在我看来,你的最终malloc()陈述应该是这样的:

Queue * retval = malloc(sizeof(*retval));

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

  1. Queue结构的定义
  2. 你是怎么打电话DequeueSynchronous的(或者,*Q变成的地方**Q

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

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

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

于 2012-04-24T03:10:55.880 回答
1

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

它也有可能已经被释放了;也许您的多个线程导致它被多次释放。

于 2012-04-24T03:08:52.143 回答