C多线程malloc坏访问全局

时间:2011-02-23 01:02:57

标签: c multithreading malloc global exc-bad-access

我有两个结构如下:

typedef struct _product
{
    unsigned int     product_id;
    time_t           my_time_stamp;
    unsigned int     lifespan;
} product;

typedef struct _queue
{
    product *   elem;
    struct _queue * next;
} queue;

我有一个全局变量头。

queue *head; 

在主要的我malloc队列的头部。

head = (queue *)malloc(sizeof(queue));

并在另一个函数中调用它

    if(head->elem == NULL) { head = newPointer; }

当我把头部摩托起来时,一切都很好。然后当它跳转到函数时,它会重置为0x0。

这是错误的方法吗?如果是这样,应该怎么做?

void producer_func(void *tid)
{   
  while(number_of_products_created < number_of_products_max) //check for completeness of task
  {
    my_str("in producer with id ");
    my_int((long)tid);
    br();
    pthread_mutex_lock(&the_mutex);
    my_str("locked by ");
    my_int((long)tid);
    br();
    while(space_in_queue >= size_of_queue)
      pthread_cond_wait(&notFull, &the_mutex); //check to see if there is room in the queue

    product *tempProduct = malloc(sizeof(product));

    //////////////enter critical region/////////////
    tempProduct->product_id = product_id_count++;
    //////////////exit critical region/////////////

    //time
    struct timeval tim;
    gettimeofday(&tim, NULL);
    tempProduct->my_time_stamp = tim.tv_sec; 
    //endtime
    tempProduct->lifespan = rand();
    //new item for queue
    queue *newPointer = malloc(sizeof(queue));
    newPointer->elem = tempProduct;
    newPointer->next = NULL;                

    //critical region//
    if(head == NULL)
    {
      head = newPointer;
    }
    else
    {
      //traverse list
      queue *tempPointer;
      tempPointer = head;
      while(tempPointer->next != NULL)
      {
        tempPointer = tempPointer->next;
      }
      tempPointer->next = newPointer;
    }
    space_in_queue++;
    number_of_products_created++;
    //end critical region//

    my_str("unlocked by ");
    my_int((long)tid);
    br();
    usleep(10000);
    my_str("num products created is ");
    my_int(number_of_products_created);
    br();
    usleep(10000);
    pthread_cond_broadcast(&notEmpty);
    pthread_mutex_unlock(&the_mutex);
    usleep(100000); //let others have a chance
  }
}

2 个答案:

答案 0 :(得分:4)

锁定互斥锁并释放互斥锁之间的代码很多。您应该尽量减少锁定所做的工作量。除了将项目添加到列表而没有锁定之外,您应该完成所有工作。只有当一切准备就绪时,您才能获取互斥锁并继续添加项目并释放互斥锁。将列表末尾的项添加为O(1)而不是O(N)操作也是一个好主意 - 保持指向结构尾部的指针。如果在互斥锁保持锁定的情况下一次睡眠10毫秒,那么你真的不会从系统中获得良好的性能(并发性)。

另一个批评是,您的产品结构将在许多64位平台上占用24个字节,而不仅仅是16.如果time_t是8字节数量,8字节数量在8字节边界上对齐,你在每个unsigned int值之后浪费了4个字节。

然而,这只是一般性的批评 - 而不是直接导致你的问题。


实质性

您似乎没有初始化使用queue分配的malloc()。由于malloc()返回未初始化的数据,因此它可以包含任何内容。在执行任何其他操作之前,必须将其转换为正确形成的队列项 - 使用初始化指针等。

答案 1 :(得分:0)

我认为head是一个全局变量。不知道为什么你的函数没有在那里找到一个好的值,但你可以避免所有的问题,只是没有它的指针变量:

queue head = {0};

然后您的列表将始终定义良好,您甚至不必检查它。您的列表的空白与否的语义会改变。

Jonathan说你的关键部分有很多代码是对的。特别是,在这样的部分睡觉真是个坏主意。