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

4

2 に答える 2

3

更新されたコードを見ると、次の行が原因でメモリが破損していると思います。

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

そこにキューへのポインタを割り当てるだけであることに注意してください。代わりに、次のように記述してください。

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

またはそれ以上:

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

2番目のバージョンは、のタイプの変更に対して堅牢であるため、より優れていretvalます。

これらの行は両方とも、「キューに十分なスペースを割り当て、retvalそれを指すようにキューポインタを設定する」と述べています。前の行は、「キューポインタに十分なスペースを割り当て、それを指すようにキューポインタを設定するretval」と述べています。古いバージョンでは、割り当てが不足していました(構造がポインターよりもほぼ確実に大きいため)。

次に、実際に割り当てたスペースを超えたキュー構造の部分に割り当てるときに、メモリの他の部分にスタンプを付けます。これにより、内部統制データの一部にスタンプが付けられmalloc()、後で無効な空きが発生する原因になると思われます。malloc()ポインタのサイズではなく、構造体のサイズをmallocするために、すべての呼び出しを変更する必要があります。

また、mallocの結果をキャストしないように注意してください。私の意見では、最終的なmalloc()ステートメントは次のようになります。

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

それでも問題が解決しない場合は、質問を編集して次の内容を含めることができますか。

  1. キュー構造の定義
  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 に答える