jonelearn
jonelearn

Reputation: 13

Inserting nodes at the end of a linked list

I'm having trouble inserting a node at the end of a linked list. The logic to me and others i have asked seems fine, however the problem remains and i'm clueless to where it might be happening.I insert the first node fine, it prints correctly. When, however, i try to insert the following node, it's as if the other has been deleted and substituted by the new one.Here are the functions i'm using :

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;
}

the accept funtion in main, is because i'm using this for a chat program. fnode and lnode in this code are, respectively, the pointers to the first and last node of the list (head and tail). So for instance i have a connected client named jack with socket number 5, him being the first and only connected client, it would rightfully print out jack and 5. however if a sencond client, amy joins in with socket 3 it would only print out amy and 3, without the first client, and so on and so forth.

Upvotes: 0

Views: 50

Answers (1)

dbush
dbush

Reputation: 225767

Inside your while loop, you declare clinfo as a instance of struct client_info. You then pass the address of that variable to client_insert to put that variable's address in the list.

When you then reach the end of the loop, that variable goes out of scope. So now you have the address of an out-of-scope variable. Subsequently using that address invokes undefined behaivor.

As to why things seem to be overwritten, that's exactly what's happening. On each loop iteration, you have an instance of struct client_info which just so happens (due to undefined behavior) to have the same address as the last time through the loop. So you're passing in the same address to client_insert each time.

You instead need to dynamically allocate an instance of struct client_info and add that to the list.

  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);

Upvotes: 1

Related Questions