结构体中使用pthread_mutex_t指针替代全局互斥锁引发多线程异常问题排查
你的多线程互斥锁问题根源:内存分配错误导致的未定义行为
兄弟,我一眼就揪出你代码里的致命问题了——线程ID数组的内存分配完全错了!这就是为什么用全局锁能正常跑,换成结构体指针就各种炸的原因,跟互斥锁本身半毛钱关系都没有,纯粹是内存越界把其他数据搞崩了。
问题出在哪?
你在main函数里写了这么一行:
id = malloc(sizeof(int) * n); // allocate id[n]
但id是pthread_t*类型,你却按int的大小来分配内存。在绝大多数现代系统里,pthread_t的尺寸都比int大(比如64位系统里int是4字节,pthread_t是8字节),这就导致你分配的内存空间根本装不下n个pthread_t对象。
接下来的操作直接触发了内存越界写入:
- 当你循环调用
pthread_create(&id[i], ...)时,会往这块不够大的内存里写入线程ID,写着写着就会溢出,覆盖后面的内存区域——刚好你后面分配的mutex和duck链表的内存就在附近,直接把互斥锁的内部状态或者链表指针给搞坏了。 - 这就解释了你遇到的所有诡异现象:
- 段错误:访问被破坏的链表指针或互斥锁结构
- 无限等待:线程ID被破坏,
pthread_join找不到正确的线程 - 断言失败:互斥锁的内部字段(比如
__owner)被越界写改成了非法值
而用全局互斥锁的时候,全局变量的内存不在堆上的这块越界区域里,没被破坏,所以程序能侥幸跑起来——但线程ID数组的问题依然存在,只是没影响到全局锁而已。
怎么修复?
只需要把内存分配那行改成按pthread_t的大小分配就行:
id = malloc(sizeof(pthread_t) * n); // 正确分配pthread_t类型的数组
另外,建议你加上内存分配失败的检查,避免后续操作访问空指针:
n = 5; // number of threads id = malloc(sizeof(pthread_t) * n); mutex = malloc(sizeof(pthread_mutex_t)); if (!id || !mutex) { perror("malloc failed"); exit(EXIT_FAILURE); } pthread_mutex_init(mutex, NULL); duck = init_chain_ducks(mutex, n); if (!duck) { perror("init_chain_ducks failed"); // 记得先释放已分配的内存再退出 free(id); free(mutex); exit(EXIT_FAILURE); }
最后,程序结束后别忘了清理内存,避免泄漏:
// 释放duck链表 struct s_duck *temp; while (duck) { temp = duck; duck = duck->next; free(temp); } // 销毁互斥锁并释放内存 pthread_mutex_destroy(mutex); free(mutex); free(id);
总结
这是典型的类型不匹配导致的内存越界问题,错误表现出来的症状和实际根源看起来不相关,很容易迷惑人。以后分配数组的时候,一定要用目标类型的sizeof,别想当然用int代替!
内容的提问来源于stack exchange,提问作者hugogogo
相关产品推荐
相关产品推荐

