【问题标题】:malloc.c error when using a struct and multiple threads使用结构和多线程时的 malloc.c 错误
【发布时间】:2012-11-03 05:37:14
【问题描述】:

我收到一个错误,我不知道如何解决。我正在尝试使用自旋锁解决“生产者-消费者”问题。我创建了一个类似“队列”的数据结构作为共享资源来放入“生产”项目,并删除要“消费”的项目。这是我的主程序的样子:

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "Queue.h"

#define DEBUG 1

Queue_t* global_queue; // create a global queue

/* thread procedure for the producer thread */
void* producer_func(void* arg)
{
   while(1) // loops infinitely
   {
      int datum = rand() % global_queue->maximum_count;

      // spin while the queue is full
      while ((global_queue->current_count) ==
         (global_queue->maximum_count));

      enqueue(global_queue, datum);
      display(global_queue);
   }
}


/* thread procedure for the consumer thread */
void* consumer_func(void* arg)
{
   while(1) // loops infinitely
   {
      int datum = 0;

      // spin while there are no items in the queue
      while(global_queue->current_count == 0);

      datum = dequeue(global_queue);
      printf("The number consumed is %d\n");
   }
}


/* Main */
int main(int argc, char** argv)
{
   if(argc != 2)
   {
      printf("Error: wrong number of command-line arguments\n");
      printf("Usage: %s <integer>\n", argv[0]);
      exit(1);
   }

   pthread_t producer;  // create producer thread
   pthread_t consumer;  // create consumer thread

   // create the queue object, get the max queue size
   //int max_count = atoi(argv[1]);
   global_queue = construct(10);
   display(global_queue);

   // intialize the random seed generator
   srand((unsigned)time(NULL));

   // create the threads and have them execute their routines
   pthread_create(&producer, NULL, &producer_func, NULL);
   pthread_create(&consumer, NULL, &consumer_func, NULL);

   // join the threads to finish
   pthread_join(producer, NULL);
   pthread_join(consumer, NULL);

   // deallocate the queue from memory
   //destruct(global_queue);

   return 0;
}

但是,当我在主例程中调用 pthread_create 时,我在 malloc.c 中得到一个奇怪的错误:

queue_demo: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted

这是我的“队列”数据结构头文件:

#ifndef QUEUE_H
#define QUEUE_H

typedef struct Queue
{
   int  current_count;
   int  maximum_count;
   int  buffer[];       // queue uses an array
} Queue_t;


// routines to implement Queue-like functionality (FIFO)
// TODO: somehow encapsulate all these features in the struct itself.
//
Queue_t* construct(int buff_size);
void     destruct (Queue_t* queue);
void     display  (Queue_t* queue);
int      dequeue  (Queue_t* queue);
void     enqueue  (Queue_t* queue, const int datum);

#endif

及实施:

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "Queue.h"

Queue_t* construct(int buff_size)
{
   Queue_t* queue = malloc(sizeof(Queue_t));

   assert(queue != NULL);
   queue->maximum_count = buff_size;
   queue->current_count = 0;

   int i = 0;

   for(; i < queue->maximum_count; ++i)
      queue->buffer[i] = 0;

   return queue;
}

void destruct(Queue_t* queue)
{
   assert(queue != NULL);
   free(queue);
   printf("Queue destroyed!\n");
}

void display(Queue_t* queue)
{
   int i = 0;

   for(; i < queue->maximum_count; ++i)
      printf("%d ", queue->buffer[i]);
   printf("\n");
}

void enqueue(Queue_t* queue, const int datum)
{
   assert(queue->current_count < queue->maximum_count);
   queue->buffer[queue->current_count] = datum;
   ++queue->current_count;
}


int dequeue(Queue_t* queue)
{
   int i = 1;
   int datum = queue->buffer[0];

   assert(queue->current_count > 0);

   for(; i < queue->maximum_count; ++i)
   {
      queue->buffer[i-1] = queue->buffer[i];
      queue->buffer[i] = 0;
   }

   --queue->current_count;

   return datum;
}

很明显,我做错了什么。但我不知道那到底是什么。我怀疑这可能与全局声明结构有关,但我不确定。任何想法将不胜感激。

【问题讨论】:

  • 家庭作业标签已被弃用并已从中删除。

标签: c pthreads malloc dynamic-memory-allocation


【解决方案1】:

您的construct() 没有为队列项目数据分配空间。

Queue_t* construct(int buff_size)
{
   Queue_t* queue = malloc(sizeof(Queue_t));

   assert(queue != NULL);
   queue->maximum_count = buff_size;
   queue->current_count = 0;

   int i = 0;

   // HERE. Where is the item data space allocation ??
   for(; i < queue->maximum_count; ++i)
      queue->buffer[i] = 0;

   return queue;
}

试试这个:

Queue_t* construct(int buff_size)
{
   // note space allocation for buffer[] bytes as well as overall structure.
   Queue_t* queue = malloc(sizeof(Queue_t) + sizeof(int) * buff_size);

   assert(queue != NULL);
   queue->maximum_count = buff_size;
   queue->current_count = 0;
   memset(queue->buffer, 0, sizeof(int)*buff_size);
   return queue;
}

我没有查看您的其余代码以确定您是否正确保护了对队列的并发访问(提到 pthread 让我怀疑您应该向 Queue_t 类型的成员添加和初始化 pthread_mutex_t ,并使用它来保护并发队列修改)。无论如何,上述问题绝对是一个问题,应该首先加以处理。

【讨论】:

  • 不幸的是,这似乎没有什么不同。我应该在输出中添加我调用 display(global_queue) 的 main 中的测试语句有效,因为输出读取数组中最大大小的所有零(在本例中为 10)。
  • @Dylan 如果它在没有进行我上面提到的更改的情况下工作,那么(a)结构没有像您在此处显示的那样定义,或者(b)完全未定义的行为。您发布的代码 clearly 没有为队列中的项目 in 分配空间,只为 Queue_t 成员分配空间。这将按定义的行为工作。也就是说,我将花一些时间查看您的其余代码。您能否在上述问题的底部发布简化的main() 来演示问题以及您正在调用的线程过程?谢谢。
  • @Dylan 感谢更新帖子。正如我所怀疑的那样,您的队列正在展示并发遍历。您需要pthread_mutex_t 在任何访问(推送、弹出、顶部等)期间锁定队列。请注意,当前您的生产者可以将数据推入队列并更新 current_count intertwined,而消费者修改(并依赖)相同的成员以弹出数据。您是否了解或需要帮助添加此功能?
  • 我为我的 Queue_t 结构制作了没有线程的测试程序,它在我的 OS X 机器上始终如一地工作。但我会注意到我的destruct 例程没有 工作,即它引发free(): invalid next size 错误。此外,我们被分配的任务是首先在不使用互斥锁或信号量的情况下实现这一点,而只使用自旋锁。使用这种全局结构是不可能的吗?
  • @Dylan 你当然可以这样做。自旋锁数据,如互斥锁,将保存在Queue_t 结构中。与队列对象中的其他数据一样,它将在队列创建时初始化,并在队列销毁时销毁。因为你有一个专门的消费者和专门的生产者,信号量也可以很好地工作,但最终你会发现使用互斥锁是far(恕我直言)中最简单的。
猜你喜欢
  • 2010-11-09
  • 1970-01-01
  • 2021-10-04
  • 2020-08-08
  • 2020-10-30
  • 2022-01-16
  • 1970-01-01
  • 2011-01-31
  • 2022-01-03
相关资源
最近更新 更多