【发布时间】:2017-02-26 14:23:57
【问题描述】:
这是一些代码的精简版本,可以完美地作为单线程程序运行。我正在尝试使其成为多线程的。目标是拥有一个全局结构列表,并在循环中为列表重新分配内存,并为循环的每次迭代将其大小扩展一个结构。我收到以下错误:
Terminated due to signal: ABORT TRAP (6)
doublefree(54652,0x70000020a000) malloc: *** error for object
0x7fbc13403400: double free
如前所述,如果线程数为 1,则它可以工作。我假设多个线程在 realloc() 期间试图释放相同的内存。但是互斥锁不应该阻止吗?列表的指针是全局的,所以不是每个线程都应该看到其他线程更改的指针吗?我看不出这与单线程版本有什么不同。如果我一遍又一遍地运行它,我最终可以得到正确的输出,所以有一些我看不到的竞争条件。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct {
char key[512];
int value;
} KV_Pair;
KV_Pair *pairList;
int count = 0;
void *doStuff(void *args);
pthread_mutex_t mutex;
int main(int argc, char *argv[]) {
pairList = malloc(sizeof(KV_Pair));
pthread_t threads[4];
int i;
for(i = 0; i < 4; i++) {
pthread_create(&(threads[i]), NULL, doStuff, NULL); }
for(i = 0; i < 4; i++) {
pthread_join(threads[i], NULL); }
free(pairList);
}
void *doStuff(void *args) {
while (1) {
pthread_mutex_lock(&mutex);
count++;
pairList =
realloc(pairList, sizeof(KV_Pair) * count);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
【问题讨论】:
-
编译器可能会使用一个寄存器来存储
pairlist,直到函数返回。尝试将pairList声明为volatile KV_Pair *pairList;以强制编译器立即将新值写回内存。 -
当
realloc()最终失败并将pairlist设置为NULL时会发生什么? -
@KlasLindbäck -
pthread_mutex_[un]lock()包含一个内存屏障。见stackoverflow.com/questions/3208060/… 和stackoverflow.com/questions/24137964/… -
@usr 我不确定发生了什么,因此这是一条评论。发布的代码似乎不应该产生双重错误。我想知道
pthread_mutext_t mutex;在技术上是否是一个未初始化的互斥体。也许pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;会改变这种行为。 -
@usr
PTHREAD_MUTEX_INITIALIZER与 0 初始化的pthread_mutex_t不同。使用 OP 代码pthread_mutex_lock(&mutex);会调用未定义的行为。正确初始化互斥锁后,代码对我有用:ideone.com/wJVKCP
标签: c multithreading pthreads