2012-04-24 82 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

相關問題