I have the following problem with this segment of code. Can some one please help?
Note: QueueItem is being created on a different thread.
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 This function is protected on access when multiple threads are running.
WorkItem * DequeueSynchronous(Queue ** Q)
{
WorkItem * retval;
pthread_mutex_lock((*Q)->QueMutex);
retval = Dequeue (Q);
pthread_mutex_unlock((*Q)->QueMutex);
return retval;
}
(*Q)->Head; is allocated my 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);
}
Also thanks for the input, I will look at 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 is called –Dequeue(&WorkQue)
All threads that call Dequeue were given &WorkQue as part of their 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]));
}
each thread calls dequeue using myWork = DequeueSynchronous(myThreadArgs->WorkQueue);
Looking at your updated code, I think you’re having memory corruption due to these lines:
Note that you’re only allocating enough for a pointer to a Queue there – you should instead write:
Or better:
The second version is better, because it’s robust to changes in the type of
retval.Both of these lines say “allocate enough space for a Queue, and set the queue pointer
retvalto point to it”. Your previous line said “allocate enough space for a Queue pointer, and set the queue pointerretvalto point to it”. The old version caused an under allocation (since the structure was almost certainly larger than a pointer).Then, when you assign to parts of the Queue structure that are past the space you’ve actually allocated, you stamp some other part of memory. I suspect that this causes you to stamp some of
malloc()s internal control data, which is what causes the invalid free later on. You will need to change all of yourmalloc()calls to malloc the size of the structure rather than the size of the pointer.Note that you should also not cast the result of malloc. In my opinion, your final
malloc()statements should look like this:If that doesn’t fix it, can you edit your question to include:
DequeueSynchronous(or, where the*Qbecomes**Q)Unrelatedly, note that you also have a bug where you don’t clear the tail when the list becomes empty after a dequeue. I suspect you may need to write:
This will clear the tail if there’s now no head in the queue.