2017-01-04 1 views
1

이중 링크 된 목록을 두 부분으로 구현하려고합니다 : 첫 번째는 목록을 만드는 실제 함수입니다. 두 번째는 시뮬레이터입니다. 몇 개의 스레드, 독자 및 작성자 (각각 while 루프에서 이중 링크 목록으로 이동하고 푸시), 목록이 너무 커지면 정리하는 가비지 수집기 스레드 (argv에 따라) . 목록은 스레드 안전을 위해 mutex와 조건부 변수를 사용합니다. 그러나 언제든지 실행할 때마다 이중 자유/메모리 손상 (빠른) 오류가 발생하고 이유를 알 수 없습니다. 나는 약간의 도움에 감사드립니다.더블 링크 된 목록 - 메모리 손상

#include <pthread.h> 
#include <time.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 

#define USAGE_ERR "Usage: ./hw3 <WNUM> <RNUM> <MAX> <TIME>\n" 

/* Argc parameter indexing consts */ 
#define INPUT_WNUM_IDX 1 
#define INPUT_RNUM_IDX 2 
#define OUTPUT_MAX_IDX 3 
#define OUTPUT_TIME_IDX 4 

typedef struct node { 
    int value; 

    struct node * previous; 
    struct node * next; 
} 
node; 

typedef struct { 
    int length; 
    node * head; 
    node * tail; 
    pthread_mutex_t mutex; 
} 
list; 

list * global_list; 
int stop_threads = 0; 
int MAX_LIST_SIZE; 
pthread_cond_t  gc_cond = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t  gc_mutex = PTHREAD_MUTEX_INITIALIZER; 

pthread_cond_t  read_cond = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t  read_mutex = PTHREAD_MUTEX_INITIALIZER; 

list * initlist_create(); 
void initlist_destroy(list * target_list); 
list * initlist_push_head(list * target_list, int value); 
int initlist_pop_tail(list * target_list); 
void initlist_remove_last_k(list * target_list, int k); 
int initlist_size(list * target_list); 
pthread_mutex_t initlist_get_mutex(list * target_list); 
void writer_thread(); 
void reader_thread(); 
void garbage_collect_thread(); 


list * initlist_create() { 
    size_t list_size = sizeof(list); 
    list * new_list = (list *) malloc(list_size); 
    new_list->head = NULL; 
    new_list->tail = NULL; 
    new_list->length = 0; 
    if (0 != pthread_mutex_init(& (new_list->mutex), NULL)) { 
     exit(errno); 
    } 
    return new_list; 
} 

void initlist_destroy(list * target_list) { 
    node * current_node; 
    node * temp_node; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    if (0 != target_list->length) { 
     current_node = target_list->head; 
     while (current_node != NULL) { 
      temp_node = current_node->next; 
      free(current_node); 
      current_node = temp_node; 
     } 
    } 

    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    if (0 != pthread_mutex_destroy(& (target_list->mutex))) { 
     exit(errno); 
    } 

    free(target_list); 
} 

list * initlist_push_head(list * target_list, int value) { 
    node * new_node; 
    size_t node_size = sizeof(node); 


    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    new_node = (node *) malloc(node_size); 
    if(NULL == new_node) 
    { 
     printf("Malloc failed\n"); 
     exit(errno); 
    } 
    new_node->value = value; 


    if (NULL != target_list->head) { 
     new_node->next = target_list->head; 
     new_node->previous = target_list->tail; 
     target_list->head->previous = new_node; 
     target_list->tail->previous = new_node; 
    } 
    else{ 
     target_list->tail = new_node; 
    } 

    target_list->head = new_node; 
    target_list->length++; 
    if(0 < target_list->length){ 
     pthread_cond_signal(&read_cond); 
    } 
    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    return target_list; 
} 

int initlist_pop_tail(list * target_list) { 
    int deleted_node_value; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    while(0 == target_list->length){ 
     pthread_cond_wait(&read_cond, &target_list->mutex); 
    } 
    node * last_node = target_list->tail; 


    if (1 == target_list->length) { 
     last_node = target_list->head; 
     target_list->head = NULL; 
     target_list->tail = NULL; 
    } else { 
     target_list->tail = last_node->previous; 
     target_list->tail->next = target_list->head; 
    } 
    deleted_node_value = last_node->value; 


    // IMPORTANT 
    // If i uncomment this, segfault and memory corruption,no idea why 
    //free(last_node); 

    target_list->length--; 
    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    // if (0 != pthread_mutex_unlock(& (read_mutex))) { 
    // exit(errno); 
    // } 

    return deleted_node_value; 
} 

void initlist_remove_last_k(list * target_list, int k) { 
    int remove_size = k; 
    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    if (k > target_list->length) 
    { 
     remove_size = target_list->length; 
    } 
    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    for (int i = 0; i < remove_size; ++i) { 
     initlist_pop_tail(target_list); 
    } 
} 

int initlist_size(list * target_list) { 
    int list_size; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    list_size = target_list->length; 

    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    return list_size; 
} 

pthread_mutex_t initlist_get_mutex(list * target_list) { 
    pthread_mutex_t list_mutex; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    list_mutex = target_list->mutex; 

    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    return list_mutex; 

} 

void writer_thread() 
{ 
    while (1) 
    { 
     if(stop_threads){ 
      return; 
     } 
     if (MAX_LIST_SIZE < initlist_size(global_list)) 
     { 
      pthread_cond_signal(&gc_cond); 
     } 
     initlist_push_head(global_list, rand()); 

    } 
} 


void reader_thread() 
{ 
    while (1) 
    { 
     if(stop_threads){ 
      return; 
     } 
     if (MAX_LIST_SIZE < initlist_size(global_list)) 
     { 
      pthread_cond_signal(&gc_cond); 
     } 
     initlist_pop_tail(global_list); 

    } 
} 

void garbage_collect_thread() 
{ 
    while(1){ 
     if(stop_threads){ 
      return; 
     } 
     pthread_cond_wait(&gc_cond, &gc_mutex); 
     int remove_count = (initlist_size(global_list)/2); 
     initlist_remove_last_k(global_list, remove_count); 
     printf("GC – %d items removed from the list\r\n", remove_count); 
     if (0 != pthread_mutex_unlock(& (gc_mutex))) { 
      exit(errno); 
     } 
    } 
} 




int main(int argc, char * * argv) { 
    /* Validate arguments */ 
    if (5 != argc) { 
     printf(USAGE_ERR); 
     exit(errno); 
    } 

    int writers_count  = atoi(argv[INPUT_WNUM_IDX]); 
    int readers_count  = atoi(argv[INPUT_RNUM_IDX]); 
    int max_run_time   = atoi(argv[OUTPUT_TIME_IDX]); 
    MAX_LIST_SIZE   = atoi(argv[OUTPUT_MAX_IDX]); 
    global_list = initlist_create(); 


    pthread_t garbage_collector_thread; 

    pthread_t writer_threads[writers_count]; 
    pthread_t reader_threads[readers_count]; 

    if (0 != pthread_create(&garbage_collector_thread, NULL, garbage_collect_thread, NULL)) 

     {  exit(errno); 
     } 

     for (int i = 0; i < writers_count; ++i) 
     { 
      if (0 != pthread_create(&writer_threads[i], NULL, writer_thread, NULL)) 
      { 
       exit(errno); 
      } 
     } 


     for (int x = 0; x < readers_count; ++x) 
     { 
      if (0 != pthread_create(&reader_threads[x], NULL, reader_thread, NULL)) 
      { 
       exit(errno); 
      } 
     } 

     sleep(max_run_time); 
     //IMPORTANT 
     //threads should die after this is set,but all threads wait for the mutex to free 
     //in gcc - see "info threads" command in gdb 

     stop_threads = 1; 
     int list_size = initlist_size(global_list); 
     printf("List size: %d", list_size); 

     for (int i = 0; i < list_size; ++i) 
     { 
      continue; 
      printf("num is %d", initlist_pop_tail(global_list)); 
     } 

     //this gets stuck also when waiting for mutex obviously... 
     initlist_destroy(global_list); 


    } 
+0

참고 : '... 1보다 큰 주석'주석의 흥미로운 유니 코드 문자 제거 문제를 해결할 것을 제안합니다. 문제의 일부가 아닌 것으로 가정합니다. – chux

+0

제거 - 그러나 주석은 컴파일하는 동안 스트라이프가됩니다 ... – lippy1234

+0

아마도'void reader_thread()'->'void * reader_thread (void * x_void_ptr)'입니다. 모든 경고를 활성화하여 발견 - 디버그 시간을 절약하고 사용해보십시오. [참조] (http://timmurphy.org/2010/05/04/pthreads-in-ca-minimal-working-example/) – chux

답변

0
#include <pthread.h> 
#include <time.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 

#define USAGE_ERR "Usage: ./hw3 <WNUM> <RNUM> <MAX> <TIME>\n" 

/* Argc parameter indexing consts */ 
#define INPUT_WNUM_IDX 1 
#define INPUT_RNUM_IDX 2 
#define OUTPUT_MAX_IDX 3 
#define OUTPUT_TIME_IDX 4 

typedef struct node { 
    int value; 

    struct node * previous; 
    struct node * next; 
} 
node; 

typedef struct { 
    int length; 
    node * head; 
    node * tail; 
    pthread_mutex_t mutex; 
} 
list; 

list * global_list; 
int stop_threads = 0; 
int MAX_LIST_SIZE; 
pthread_cond_t  gc_cond = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t  gc_mutex = PTHREAD_MUTEX_INITIALIZER; 

pthread_cond_t  read_cond = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t  read_mutex = PTHREAD_MUTEX_INITIALIZER; 

list * initlist_create(); 
void initlist_destroy(list * target_list); 
list * initlist_push_head(list * target_list, int value); 
int initlist_pop_tail(list * target_list); 
void initlist_remove_last_k(list * target_list, int k); 
int initlist_size(list * target_list); 
pthread_mutex_t initlist_get_mutex(list * target_list); 
void writer_thread(); 
void reader_thread(); 
void garbage_collect_thread(); 


list * initlist_create() { 
    size_t list_size = sizeof(list); 
    list * new_list = (list *) malloc(list_size); 
    new_list->head = NULL; 
    new_list->tail = NULL; 
    new_list->length = 0; 
    if (0 != pthread_mutex_init(& (new_list->mutex), NULL)) { 
     exit(errno); 
    } 
    return new_list; 
} 

void initlist_destroy(list * target_list) { 
    node * current_node; 
    node * temp_node; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    if (0 != target_list->length) { 
     current_node = target_list->head; 
     while (current_node != NULL) { 
      temp_node = current_node->next; 
      free(current_node); 
      current_node = temp_node; 
     } 
    } 

    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    if (0 != pthread_mutex_destroy(& (target_list->mutex))) { 
     exit(errno); 
    } 

    free(target_list); 
} 

list * initlist_push_head(list * target_list, int value) { 
    node * new_node; 
    size_t node_size = sizeof(node); 


    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    new_node = (node *) malloc(node_size); 
    if (NULL == new_node) 
    { 
     printf("Malloc failed\n"); 
     exit(errno); 
    } 
    new_node->value = value; 

    if (0 == target_list->length) { 
     target_list->tail = new_node; 
    } 
    else { 
     target_list->head->previous = new_node; 
    } 
    new_node->next = target_list->head; 
    target_list->head = new_node; 

    pthread_cond_signal(&read_cond); 
    target_list->length++; 
    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    return target_list; 
} 

int initlist_pop_tail(list * target_list) { 
    int deleted_node_value; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    while(0 == target_list->length) { 
     pthread_cond_wait(&read_cond, &target_list->mutex); 
    } 
    node * last_node = target_list->tail; 
    deleted_node_value = last_node->value; 
    target_list->tail = last_node->previous; 
    if (last_node->previous != NULL) { 
     last_node->previous->next = NULL; 
     } 
    else 
    { 
     target_list->head = NULL; 

    } 
    target_list->length--; 
    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    last_node->next = NULL; 
    last_node->previous = NULL; 
    free(last_node); 



    // node *result = NULL; 
    // lock(&list_ptr->mutex); 
    // if (list_ptr->head != NULL) { 
    //  result = list_ptr->tail; 
    //  list_ptr->tail = result->prev; 
    //  if (result->prev != NULL) { 
    //   result->prev->next = NULL; 
    //  } 
    //  else { 
    //   list_ptr->head = NULL; 
    //  } 
    //  list_ptr->length--; 
    // } 
    // unlock(&list_ptr->mutex); 
    // if (result != NULL) { 
    //  result->next = NULL; 
    //  result->prev = NULL; 
    // } 
    // return result; 

    return deleted_node_value; 
} 

void initlist_remove_last_k(list * target_list, int k) { 
    int remove_size = k; 
    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    if (k > target_list->length) 
    { 
     remove_size = target_list->length; 
    } 
    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 
    for (int i = 0; i < remove_size; ++i) { 
     initlist_pop_tail(target_list); 
    } 
} 

int initlist_size(list * target_list) { 
    int list_size; 

    if (0 != pthread_mutex_lock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    list_size = target_list->length; 

    if (0 != pthread_mutex_unlock(& (target_list->mutex))) { 
     exit(errno); 
    } 

    return list_size; 
} 

pthread_mutex_t initlist_get_mutex(list * target_list) { 
    pthread_mutex_t list_mutex; 

    list_mutex = target_list->mutex; 

    return list_mutex; 

} 

void writer_thread() 
{ 
    while (1) 
    { 
     if (stop_threads) { 
      return; 
     } 
     if (MAX_LIST_SIZE < initlist_size(global_list)) 
     { 

      pthread_cond_signal(&gc_cond); 
     } 
     initlist_push_head(global_list, rand()); 

    } 
} 


void reader_thread() 
{ 
    while (1) 
    { 
     if (stop_threads) { 
      return; 
     } 
     if (MAX_LIST_SIZE < initlist_size(global_list)) 
     { 
      pthread_cond_signal(&gc_cond); 
     } 
     initlist_pop_tail(global_list); 

    } 
} 

void garbage_collect_thread() 
{ 
    while(1) { 
     if (stop_threads) { 
      return; 
     } 

     if (0 != pthread_mutex_lock(& (gc_mutex))) { 
      exit(errno); 
     } 
     pthread_cond_wait(&gc_cond, &(gc_mutex)); 
     int remove_count = (initlist_size(global_list)/2); 
     if (0 == remove_count){ 
      continue; 
     } 
     initlist_remove_last_k(global_list, remove_count); 
     printf("GC – %d items removed from the list\r\n", remove_count); 
     if (0 != pthread_mutex_unlock(& (gc_mutex))) { 
      exit(errno); 
     } 
    } 
} 

int main(int argc, char * * argv) { 
    /* Validate arguments */ 
    if (5 != argc) { 
     printf(USAGE_ERR); 
     exit(errno); 
    } 

    int writers_count  = atoi(argv[INPUT_WNUM_IDX]); 
    int readers_count  = atoi(argv[INPUT_RNUM_IDX]); 
    int max_run_time   = atoi(argv[OUTPUT_TIME_IDX]); 
    MAX_LIST_SIZE   = atoi(argv[OUTPUT_MAX_IDX]); 
    global_list = initlist_create(); 


    pthread_t garbage_collector_thread; 

    pthread_t writer_threads[writers_count]; 
    pthread_t reader_threads[readers_count]; 

    if (0 != pthread_create(&garbage_collector_thread, NULL, garbage_collect_thread, NULL)) 

    { exit(errno); 
    } 

    for (int i = 0; i < writers_count; ++i) 
    { 
     if (0 != pthread_create(&writer_threads[i], NULL, writer_thread, NULL)) 
     { 
      exit(errno); 
     } 
    } 


    for (int x = 0; x < readers_count; ++x) 
    { 
     if (0 != pthread_create(&reader_threads[x], NULL, reader_thread, NULL)) 
     { 
      exit(errno); 
     } 
    } 


    sleep(max_run_time); 
    stop_threads = 1; 
    int list_size = initlist_size(global_list); 
    printf("List size: %d\r\n", list_size); 

    for (int i = 0; i < readers_count; ++i) 
    { 
     pthread_cancel(&reader_threads[i]); 
    } 
    for (int i = 0; i < writers_count; ++i) 
    { 
     pthread_cancel(&writer_threads[i]); 
    } 

    for (int i = 0; i < list_size; ++i) 
    { 
     printf("num is %d\r\n", initlist_pop_tail(global_list)); 
    } 

    initlist_destroy(global_list); 


} 
0

나는 디버거에서 코드를 실행하고 initlist_destroy에서이 코드에 두 번 같은 포인터를 해제하려는 시도가 :

if (0 != target_list->length) { 
    current_node = target_list->head; 
    while (current_node != NULL) { 
     temp_node = current_node->next; 
     // Added the following line to view pointer values 
     printf("Freeing %p...\n", current_node); 
     free(current_node); 
     current_node = temp_node; 
    } 
} 

내가 포인터 값을 출력, I

GC – 5 items removed from the list 
List size: 4 
Freeing 0x7fc1a1602d20... 
Freeing 0x7fc1a15045e0... 
Freeing 0x7fc1a3569c40... 
Freeing 0x7fc1a3569c40... 

위에서 보듯이 동일한 포인터를 두 번 해제하려고 시도합니다. 목록 처리 코드에 결함이 있습니다. 이것은 놀라운 일이 아닙니다. 링크 된 목록 코드는 작성하기가 어렵습니다.

내 추천

  1. 목록에 적은 수의 항목으로 추가 연결리스트를 작성 단일 스레드 프로그램을 작성하는 것입니다 (예 3)
  2. 목록에서 각 항목을 제거합니다
  3. 목록이

내가 읽기 쉬운의 목록 포인터를 인쇄하는 기능을 작성 비어 검증 방식 (예 : 16 진수 값의 테이블). 목록을 수정할 때마다 해당 함수를 호출하십시오. 자신이 뭘 잘못하고 있는지 쉽게 알아야합니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <pthread.h> 
#include <inttypes.h> 

#define PTR_FMT "0x%016" PRIXPTR 

void perror_location(const char *file, int line_number) { 
    char location[80]; 
    snprintf(location, sizeof(location), "%s:%d", file, line_number); 
    perror(location); 
    exit(errno); 
} 

#define PERROR() perror_location(__FILE__, __LINE__) 

void *malloc_safe(size_t size) { 
    void *result = malloc(size); 
    if (NULL == result) { 
     PERROR(); 
    } 
    return result; 
} 

#define MALLOC(type) \ 
    (type *) malloc_safe(sizeof(type)) 

void lock(pthread_mutex_t *mutex) { 
    if (0 != pthread_mutex_lock(mutex)) { 
     PERROR(); 
    } 
} 

void unlock(pthread_mutex_t *mutex) { 
    if (0 != pthread_mutex_unlock(mutex)) { 
     PERROR(); 
    } 
} 

typedef struct _node { 
    int value; 
    struct _node *next; 
    struct _node *prev; 
} node; 

typedef struct _list { 
    node *head; 
    node *tail; 
    size_t length; 
    pthread_mutex_t mutex; 
} list; 

list *list_init(void) { 
    list *result = MALLOC(list); 
    result->head = NULL; 
    result->tail = NULL; 
    result->length = 0; 
    if (0 != pthread_mutex_init(&result->mutex, NULL)) { 
     PERROR(); 
    } 
    return result; 
} 

node *list_add(list *list_ptr, int value) { 
    node *result = MALLOC(node); 
    result->value = value; 
    result->next = NULL; 
    result->prev = NULL; 
    lock(&list_ptr->mutex); 
    if (list_ptr->head == NULL) { 
     list_ptr->head = result; 
     list_ptr->tail = result; 
    } 
    else { 
     result->prev = list_ptr->tail; 
     list_ptr->tail->next = result; 
     list_ptr->tail = result; 
    } 
    list_ptr->length++; 
    unlock(&list_ptr->mutex); 
    return result; 
} 

node *list_remove(list *list_ptr) { 
    node *result = NULL; 
    lock(&list_ptr->mutex); 
    if (list_ptr->head != NULL) { 
     result = list_ptr->tail; 
     list_ptr->tail = result->prev; 
     if (result->prev != NULL) { 
      result->prev->next = NULL; 
     } 
     else { 
      list_ptr->head = NULL; 
     } 
     list_ptr->length--; 
    } 
    unlock(&list_ptr->mutex); 
    if (result != NULL) { 
     result->next = NULL; 
     result->prev = NULL; 
    } 
    return result; 
} 

void list_print(list *list_ptr) { 
    lock(&list_ptr->mutex); 
    printf("----------\n"); 
    printf("length = %ld\n", list_ptr->length); 
    printf("%-18s %-18s %-18s\n", "list", "list->head", "list->tail"); 
    printf(PTR_FMT " " PTR_FMT " " PTR_FMT "\n", 
      (uintptr_t) list_ptr, 
      (uintptr_t) list_ptr->head, 
      (uintptr_t) list_ptr->tail); 
    if (list_ptr->head != NULL) { 
     printf("%-18s %-18s %-18s\n", "node", "node->next", "node->prev"); 
     node *current = list_ptr->head; 
     do { 
      printf(PTR_FMT " " PTR_FMT " " PTR_FMT "\n", 
        (uintptr_t) current, 
        (uintptr_t) current->next, 
        (uintptr_t) current->prev); 
      current = current->next; 
     } while (current != NULL); 
    } 
    unlock(&list_ptr->mutex); 
} 

int main(void) { 
    list *linked_list = list_init(); 

    printf("Add items...\n"); 
    for (int value = 1; value <= 3; value++) { 
     list_add(linked_list, value); 
     list_print(linked_list); 
    } 

    printf("Remove items...\n"); 
    while (1) { 
     node *result = list_remove(linked_list); 
     if (NULL == result) { 
      break; 
     } 
     free(result); 
     list_print(linked_list); 
    } 

    if ((linked_list->head != NULL) || (linked_list->tail != NULL)) { 
     printf("ERROR: List is not empty\n"); 
     return EFAULT; 
    } 

    free(linked_list); 

    return 0; 
} 

출력

Add items... 
---------- 
length = 1 
list    list->head   list->tail   
0x00007F8180C031B0 0x00007F8180C0x00007F8180C
node    node->next   node->prev   
0x00007F8180C0x0000000000000000 0x0000000000000000 
---------- 
length = 2 
list    list->head   list->tail   
0x00007F8180C031B0 0x00007F8180C0x00007F8180C03230 
node    node->next   node->prev   
0x00007F8180C0x00007F8180C03230 0x0000000000000000 
0x00007F8180C03230 0x0000000000000000 0x00007F8180C
---------- 
length = 3 
list    list->head   list->tail   
0x00007F8180C031B0 0x00007F8180C0x00007F8180C03250 
node    node->next   node->prev   
0x00007F8180C0x00007F8180C03230 0x0000000000000000 
0x00007F8180C03230 0x00007F8180C03250 0x00007F8180C
0x00007F8180C03250 0x0000000000000000 0x00007F8180C03230 
Remove items... 
---------- 
length = 2 
list    list->head   list->tail   
0x00007F8180C031B0 0x00007F8180C0x00007F8180C03230 
node    node->next   node->prev   
0x00007F8180C0x00007F8180C03230 0x0000000000000000 
0x00007F8180C03230 0x0000000000000000 0x00007F8180C
---------- 
length = 1 
list    list->head   list->tail   
0x00007F8180C031B0 0x00007F8180C0x00007F8180C
node    node->next   node->prev   
0x00007F8180C0x0000000000000000 0x0000000000000000 
---------- 
length = 0 
list    list->head   list->tail   
0x00007F8180C031B0 0x0000000000000000 0x0000000000000000 

난 내 자신의 목록 처리를 해결하기 위해 디버거를 사용 :

업데이트 나는 위의 제안을 구현하는 프로그램을 썼습니다. 나는 당신의 것을 고치는 데 하나를 사용하는 것이 좋습니다.

+0

initlist_destroy 함수를 살펴 보았습니다.하지만 왜 오류가 발생하는지 파악할 수 없습니다. 아이디어가 있습니까? – lippy1234

+0

예, 목록에 요소를 추가하거나 목록에서 요소를 제거 할 때 잘못된 동작을하고 있습니다. 목록의 마지막 요소의'next' 포인터는'NULL'이어야합니다. 대신 목록의 마지막 요소를 가리 킵니다. 디버거에서 목록 처리 코드를 단계별로 실행하여 문제를 볼 수 있어야합니다. –

+0

코드에서 변경되었지만 응답이 down.but입니다.하지만 10 명의 작성자, 10 명의 독자, 10 meax 크기 및 100 초로 코드를 실행하면 initlist_pop_tail 함수의 cond_wait에 멈추게됩니다. 왜 그럴 수 없어? – lippy1234