C 多线程 malloc 全局访问错误
我有两个结构如下:
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;
在 main 中,我 malloc 队列的头部。
head = (queue *)malloc(sizeof(queue));
并在另一个函数中调用它
if(head->elem == NULL) { head = newPointer; }
当我 malloc 头时一切都很好。然后,当它跳转到该函数时,它会重置为 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(¬Full, &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(¬Empty);
pthread_mutex_unlock(&the_mutex);
usleep(100000); //let others have a chance
}
}
I have 2 structs as follows:
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;
I have a global variable head.
queue *head;
In main I malloc the head of the queue.
head = (queue *)malloc(sizeof(queue));
And Call it in another function
if(head->elem == NULL) { head = newPointer; }
When I malloc the head everything is fine. Then when it jumps to the function it resets to 0x0.
Is this the wrong way to do this? If so how should it be done?
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(¬Full, &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(¬Empty);
pthread_mutex_unlock(&the_mutex);
usleep(100000); //let others have a chance
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
锁定互斥体和释放互斥体之间的代码量非常大。您应该致力于最大限度地减少持有锁时完成的工作量。您应该完成所有工作,除了将项目添加到不带锁的列表中。只有当一切准备就绪后,您才能获取互斥体并继续添加项目并释放互斥体。将项目添加到列表末尾的操作可能是 O(1) 而不是 O(N) 的好主意 - 保留指向结构尾部的指针。如果在互斥体保持锁定的情况下一次休眠 10 毫秒,那么系统确实无法获得良好的性能(并发性)。
另一个批评是,您的产品结构在许多 64 位平台上将占用 24 个字节,而不仅仅是 16 个。如果
time_t
是一个 8 字节数量,并且 8 字节数量在 8 字节边界上对齐,在每个unsigned int
值后面浪费了 4 个字节。然而,这只是一般性的批评——并不是问题的直接根源。
实质性
您似乎没有初始化使用
malloc()
分配的queue
。由于malloc()
返回未初始化的数据,因此它可以包含任何内容。在执行其他操作之前,必须将其转换为格式正确的队列项 - 具有初始化的指针等。That's an awful lot of code between locking the mutex and releasing it. You should aim to minimize the amount of work done with the lock held. You should do all the work except add the item to the list without the lock. Only when everything is ready do you grab the mutex and go ahead with adding the item and release the mutex. It might be a good idea to make adding the item at the end of the list an O(1) rather than O(N) operation too - keep a pointer to the tail of the structure. You really won't get good performance (concurrency) out of the system if you sleep for 10 milliseconds at a time with the mutex held locked.
Another critique is that your product structure will occupy 24 bytes on many 64-bit platforms, rather than just 16. If
time_t
is an 8-byte quantity and 8-byte quantities are aligned on 8-byte boundaries, you waste 4 bytes after each of theunsigned int
values.However, that's just general critique - not directly a source of your problem.
Substantive
You do not seem to be initializing the
queue
which you allocate withmalloc()
. Sincemalloc()
returns uninitialized data, it can contain anything. Before you do anything else, you must turn it into a properly formed queue item - with initialized pointers etc.我认为
head
是一个全局变量。不知道为什么你的函数在那里找不到一个好的值,但是你可以通过不使用指针变量来避免所有问题:然后你的列表将始终被很好地定义,你甚至不需要检查它。不过,您的列表是否为空的语义将会改变。
乔纳森是对的,您的关键部分中有大量代码。尤其是在这样的区域睡觉实在是一个坏主意。
I suppose that
head
is a global variable. No idea why your function doesn't find a good value in there, but you could avoid all your problems by just not having it a pointer variable:Then your list would always be well defined and you'd never even have to check it. Your semantics for your list being empty or not would change though.
And Jonathan is right that you have an awful lot of code in your critical section. In particular, Sleeping inside such a section is really a bad idea.