在链表的末尾插入节点

时间:2017-12-08 16:25:57

标签: c linux pointers linked-list

我在链接列表末尾插入节点时遇到问题。我和其他人的逻辑看起来很好,但问题仍然存在,我对它可能发生的地方一无所知。我插入第一个节点,它打印正确。但是,当我尝试插入以下节点时,就好像另一个节点被删除并被新节点替换。这是我正在使用的函数:

struct client_info{
  pthread_t client_ID;
  int sockfd;
  struct chat chats;
  char user[NAMELEN];
  struct client_info *next;
  char current[NAMELEN];
};

struct header{
  struct client_info *fnode, *lnode;
}client_head;
void client_insert(struct client_info *node){
  if(client_head.fnode == NULL){
    client_head.fnode = node;
    client_head.lnode = node;
  }
  else{
    client_head.lnode->next = node;
    client_head.lnode = node;
  }
}
void display_clients(){
  struct client_info *tmp = client_head.fnode;
  while(tmp!=NULL){
    printf("Username: %s\nSocket: %d\n--------------------\n",tmp->user,tmp->sockfd);
    tmp = tmp->next;
  }
}

//inside main.
while(1){
    size = sizeof(struct sockaddr_in);
    if((clientfd = accept(sockfd, (struct sockaddr *)&client_addr,(socklen_t*)&size))>0){
      printf("Client accepted\n");
      struct client_info clinfo;
      clinfo.sockfd = clientfd;
      clinfo.next = NULL;
      pthread_mutex_lock(&mutex);
      client_insert(&clinfo);
      pthread_mutex_unlock(&mutex);
      pthread_create(&clinfo.client_ID, NULL, client_commands_handler, (void *)&clinfo);
    }
    else{
      perror("accept");
    }
  }
  return 0;
}

主要的接受功能,是因为我将它用于聊天程序。此代码中的fnode和lnode分别是指向列表的第一个和最后一个节点(头部和尾部)的指针。 所以例如我有一个名为jack的连接客户端,插座号为5,他是第一个也是唯一一个连接的客户端,它会正确地打印出jack和5.但是如果是一个sencond客户端,amy加入socket 3它只会打印出来艾米和3,没有第一个客户,依此类推。

1 个答案:

答案 0 :(得分:1)

while循环中,您将clinfo声明为struct client_info的实例。然后,将该变量的地址传递给client_insert,将该变量的地址放入列表中。

当您到达循环结束时,该变量超出范围。所以现在你有一个超出范围的变量的地址。随后使用该地址调用undefined behaivor

至于为什么事情似乎被覆盖,这正是发生的事情。在每次循环迭代中,您有一个struct client_info实例,它恰好发生(由于未定义的行为)与上一次循环相同的地址。因此,您每次都会将同一地址传递给client_insert

您需要动态分配struct client_info的实例并将其添加到列表中。

  struct client_info *clinfo = malloc(sizeof(*clinfo);
  if (!clinfo) {
      perror("malloc failed");
      exit(1);
  }
  clinfo->sockfd = clientfd;
  clinfo->next = NULL;
  pthread_mutex_lock(&mutex);
  client_insert(clinfo);
  pthread_mutex_unlock(&mutex);
  pthread_create(&clinfo->client_ID, NULL, client_commands_handler, clinfo);