2017-12-08 9 views
0

링크 된 목록의 끝에 노드를 삽입하는 데 문제가 있습니다. 나와 다른 사람에게 논리는 괜찮은 것처럼 보이지만 문제는 여전히 남아 있으며 어디에서 일어날 지 알 수 없습니다. 첫 번째 노드를 잘 삽입하면 올바르게 인쇄됩니다.링크 된 목록의 끝에 노드 삽입

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

주에서 연료 소모량을 수락된다, 그러나, 나는 다음과 같은 노드를 삽입 할 때, 다른 하나는 새로운 one.Here에 의해 삭제되고 대체 된 경우 내가 사용하는 기능은, 그것은이다 왜냐하면 나는 이것을 채팅 프로그램에 사용하고 있기 때문이다. 이 코드의 fnode 및 lnode는 각각 목록의 첫 번째 및 마지막 노드 (머리 및 꼬리)에 대한 포인터입니다. 예를 들어, 나는 연결된 클라이언트가 소켓 번호 5의 잭을 가지고 있고, 연결 클라이언트가 첫 번째이고 연결된 클라이언트가 5 번 밖에 인쇄되지 않습니다. 그러나 sencond 클라이언트 인 경우 amy가 소켓 3과 결합하여 인쇄합니다 밖으로 amy 및 3, 첫 번째 클라이언트없이, 등등.

+2

'lnode'란 무엇입니까? 'fnode'는 무엇입니까? 스레딩 및 유닛 구현 ​​테스트와 같은 관련성없는 코드를 제거하십시오. 또한 제대로 포맷 된 [mcve]를 제공하십시오. –

+0

디버거를 가지고 있습니까? 목록의 헤드에 대한 포인터가 각 스레드에 대해 동일한 지 여부를 확인할 수 있습니다. 스레드 안전 목록을 만들기 위해 특별한주의가 필요합니다. 정확히 무슨 일이 일어 났는지 –

답변

1

while 루프 안에 clinfostruct 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); 
+0

! 고마워요. – jonelearn