【问题标题】:pthread segmentation fault with linked lists - beginner链表的 pthread 分段错误 - 初学者
【发布时间】:2012-03-08 13:02:22
【问题描述】:

这是我第一次使用 pthreads。我遇到了麻烦,因为有时我的程序段错误,有时却没有。我的程序中有一些函数可以执行一些基本任务(用 C 语言编写),例如创建链表、向列表中添加项目以及从列表中删除项目。每个函数都会创建自己的列表副本,因此我认为它们不会相互交互,因此不需要互斥锁。无论如何,如果有人有任何想法或者如果有任何“常见”初学者 pthread 错误,下面是我的代码。

我并行运行每个函数 1000 次,有时会出现段错误,有时不会。我注意到它只发生在这 3 个功能的组合中。

过程如下: - 创建线程 - 并行运行线程 - 每个线程调用虚拟函数来执行给定次数的任务 - 那个虚拟函数也调用其他函数

我认为这可能与内存使用/分配有关,因为所有这些功能都与创建/删除链表节点有关。非常感谢。

这里是创建和连接:

 pthread_create(&t7, NULL, (void*)&p4, (void*)var);
 pthread_create(&t8, NULL, (void*)&p5a, (void*)var);
 pthread_create(&t9, NULL, (void*)&p5b, (void*)var);
 pthread_join(t7, NULL);
 pthread_join(t8, NULL);
 pthread_join(t9, NULL);

以下是虚拟函数:

void p4(int *nptr){
  int n = *nptr;
  // Get current time
  struct timeval t0, t1;
  gettimeofday(&t0,0);

  int i = 0;
  LIST *list = (LIST*)malloc(sizeof(LIST));
      for(i=0;i<n;i++){
    f4(list);
    deleteList(list);
  }
  // Get current time and find time elapsed
  gettimeofday(&t1,0);
  float elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
      printf("Successful execution of p4 in %f microseconds.\n", elapsed);
  free(list);
}
void p5a(int *nptr){
  int n = *nptr;
  LIST *list = (LIST*)malloc(sizeof(LIST));
  f4(list);
  // Get current time
  struct timeval t0, t1;
  gettimeofday(&t0,0);

  int i = 0;
      for(i=0;i<n;i++){
    f5a(list);
  }
  // Get current time and find time elapsed
  gettimeofday(&t1,0);
  float elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
  printf("Successful execution of p5a in %f microseconds.\n", elapsed);
}
void p5b(int *nptr){
  int n = *nptr;
  LIST *list = (LIST*)malloc(sizeof(LIST));
  f4(list);
  int i = 0;
      for(i=0;i<n;i++){
    f5a(list);
  }
  // Get current time
  struct timeval t0, t1;
  gettimeofday(&t0,0);
  for(i=0;i<n;i++){
    f5b(list);
  }
  // Get current time and find time elapsed
  gettimeofday(&t1,0);
  float elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
  printf("Successful execution of p5b in %f microseconds.\n", elapsed);
}

以下是用于执行常规任务的函数:

// FUNCTION: initialize a linked list with pointers and insert a last element
void f4(LIST *L1){
  // initialize an empty linked list if L1 = null
  if(L1->head == NULL){
    NODE *n = (NODE *)malloc(sizeof(NODE));
    L1->head = n;
    L1->tail = n;
    L1->tail->next = NULL;
    n->data = 1;
  }
  // traverse the linked list to the end
  NODE *iter = L1->head;
  while(iter->next != NULL)
    iter = iter->next;
  // insert a new 2 element
  NODE *new = (NODE *)malloc(sizeof(NODE));
  new->data = 2; // arbitrary for testing
  new->next = NULL;
  iter->next = new;
  L1->tail = new;
}

// FUNCTION: add an item to the end of a list (queue)
void f5a(LIST *list){
  NODE *new = (NODE *)malloc(sizeof(NODE));
  new->data = 999;
  new->next = NULL;
  list->tail->next = new;
  list->tail = new;
}

// FUNCTION: remove an item from the beginning of a list (queue)
void f5b(LIST *list){
  NODE *remove = list->head;
  list->head = list->head->next;
  free(remove);
}

【问题讨论】:

  • 我怀疑这些线程与此有关。您似乎没有共享任何内存。我会考虑更好地测试您的列表功能。 (另外,jeebus,给它们起个描述性的名字!)
  • 这似乎并不重要,但尽量不要使用保留关键字作为变量名:'new' 关键字在 C++ 中是保留的。我知道您的程序是用 C 语言编写的,而不是用 C++ 编写的,但是……以防万一。也许有一天有人(例如你)会想把它移植到 C++ ...
  • 你也可以发布deleteList代码吗?
  • 您传递给 pthread_create 的“var”是什么?是指针吗?此外,它的价值是什么,它会在主线程中并行更新。最好按原样发布完整代码。

标签: c unix pthreads


【解决方案1】:

如果您阅读 malloc 手册页,您会发现它不会将分配的内存初始化为 0。因此,您在 p4p5ap5b 函数中使用了 malloc 内存。在此之后,您调用没有初始化 LIST 内容的 f4 函数。

p4 函数中,您使用if(L1-&gt;head == NULL) 检查有效指针,但它可能不为空。所以你不要为L1-&gt;head 分配内存,并且在这个函数之后,在f5b 函数中你正在释放一个未分配的指针。

建议:

  • 始终初始化分配的区域。
  • 始终检查 malloc 返回的指针

【讨论】:

  • 感谢您的洞察力。这就是问题所在。我将 head 初始化为 NULL,一切都被原谅了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多