2012-04-24 93 views
1

我对这段代码有以下问题。有人可以帮忙吗?glibc detected ***免费():无效指针

注意: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) - > Head;分配给我的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。

EDIT 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作为其参数的个数一部分的所有线程;

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

回答

3

看你更新的代码,我想你遇到内存损坏是由于这些行:

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

请注意,你只是一个队列分配足够的指针有 - 你应该写的,而不是:

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

或者更好:

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

第二个版本是更好的,BEC因为它对retval类型的变化是强健的。

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

然后,当您分配到已经分配的空间的部分队列结构时,会为内存的其他部分添加标记。我怀疑这会导致你戳一些malloc()的内部控制数据,这是后来导致无效的原因。您需要将所有malloc()调用更改为malloc与结构的大小,而不是指针的大小。

请注意,你也应该not cast the result of malloc。在我看来,你的最后陈述malloc()应该是这样的:

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

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

  1. 队列结构的定义
  2. 如何你打电话DequeueSynchronous(或,其中*Q变得**Q

无关紧要的是,请注意,您也有一个错误,即当列表变为空时,您不清除尾部。我怀疑你可能需要写:

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

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

+0

valgrind +1。 – vanza 2012-04-24 03:13:27

+0

我已经使用了gdb,但会给valgrind一个镜头。双倍免费是不太可能的。 感谢您的输入 – chris 2012-04-24 22:50:22

+0

这个错误没有显示在Valgrind :( – chris 2012-04-25 21:03:00

1

没有什么本质上的区别这一点,就可以看出。但问题必须是tmp(换句话说,进入该函数时为(*Q)->Head)不是指向由malloc()分配的块的指针。如果它是以其他方式分配的 - 或者它是一个指向块的中间而不是开始的指针 - 那么你不能用free()释放它。

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

+0

嗯(* Q) - > Head是由malloc分配的,当我运行多个线程时,一次只能有一个队列可以访问Queue。感谢您的意见。 – chris 2012-04-24 22:53:13

相关问题