Сортированный двусвязный список дает ошибку шины при обращении в обратном направлении - PullRequest
1 голос
/ 11 августа 2011

У меня есть общая реализация двусвязного списка, и я работал над вставкой. После вставки я пытаюсь перебрать список в обратном направлении, начиная с ноги, и получаю ошибку шины Чтобы протестировать код и попытаться изолировать ошибку, в которую я поместил операторы print (не самая лучшая процедура отладки, но полезная для того, чтобы с первого взгляда сказать мне, что делает мой код). Чтобы попытаться выяснить, где возникает проблема, после каждой вставки я спрашиваю значение второго-последнего элемента в списке. Я всегда вставляю элементы в порядке 5, 2, 10, 80, 4, 1, 7, 8, и после вставки 4 в список он последовательно задыхается. Полный код программы приведен ниже.

dlist_t *
insert_in_order (dlist_t *list, void *value, size_t size,
    int (*cmp_fptr)(const void *, const void *))
{
dlnode_t * prev = NULL;
dlnode_t * current = list->head;
dlnode_t * newnode = safe_malloc(sizeof(dlnode_t));

newnode->data = value;
newnode->next = NULL;
newnode->prev = NULL;

printf("Beginning list loop for %d.\n", *(int *) newnode->data);
while (current != NULL && cmp_fptr(newnode->data, current->data) != -1)
{
    prev = current;
    current = current->next;
}
printf("Insertion point found.\n");

newnode->next = current;
newnode->prev = prev;

if (prev == NULL)
{
    printf("Setting for new head\n");
    list->head = newnode;
}
else
{
    printf("Setting previous next to new node\n");
    prev->next = newnode;
}

if (current == NULL)
{
    printf("setting for new foot.");
    list->foot = newnode;
}
else
{
    printf("Setting for new current previous\n");
    current->prev = newnode;
}

list->list_len++;
list->size = sizeof(list);
printf("Insertion compete for %d\n\n", *(int *) newnode->data);
printf("Data for surrounding:\n");
if(newnode->next !=NULL)
{
    printf("Next is %d \n", *(int *) newnode->next->data);
}
if(newnode->prev != NULL)
{
    printf("Prev is %d \n\n", *(int *) newnode->prev->data);
}

if(list->foot->prev != NULL)
{
    printf("Gonna print secondlast!\n");
    printf("secondlast is%d \n\n", *(int *)list->foot->prev->data);
}

return list;
}

Определения списка очень просты, просто

struct dlnode
{
  void *data;     /* A pointer to a generic satellite data payload */ 
  dlnode_t *next; /* A pointer to the next item in the list */
  dlnode_t *prev; /* A pointer to the previous item in the list */
};

typedef struct
{
  dlnode_t *head; /* A pointer to the head node of the list */
  dlnode_t *foot; /* A pointer to the foot node of the list */
  int list_len;   /* Total number of items in the list */
  int size;       /* Size of the list in bytes */
} dlist_t;

Вы можете изменить определение функции по своему усмотрению, а safe_malloc - это просто ярлык для malloc, который можно заменить, если вы сами тестируете код. cmp_fptr - указатель на функцию для простого метода «больше, чем b».

РЕДАКТИРОВАТЬ: ОБНОВЛЕНИЕ Линия

printf("secondlast is%d \n\n", *(int *)list->foot->prev->data);

это то, что заставляет программу останавливаться, я использовал отладчик. При вставке элементов в список он останавливается в этой строке после нескольких вставок. Ниже приведен мой тестовый код, который я сейчас использую.

int *
alloc_data (int val)
{
  int *rv = safe_malloc (sizeof (int));
  *rv = val;
  return (rv);
}

int
main (void) 
{
  dlist_t *list = NULL;
  int *num = NULL, *rv = NULL;
  dlnode_t *tnode = NULL;

  list = make_empty_list ();

  list = insert_in_order (list, alloc_data (5), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (2), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (10), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (80), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (4), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (1), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (7), sizeof(int), cmp_int); 
  list = insert_in_order (list, alloc_data (8), sizeof(int), cmp_int);
  return(EXIT_SUCCESS);
}

Есть немного больше, но это все, что я сейчас тестирую.

Спасибо за подсказку по списку -> размеру, я не совсем уверен, что я думал об этом изначально.

edit2: спасибо за поиск ошибок safe_malloc, я думал, что это было причиной проблемы, но я все еще получаю ту же ошибку. Отладчик выдает мне sigsegv (ошибка сегментации) после вставки 4, и он попадает в строку, где для здравого смысла я запрашиваю список-> foot-> prev-> data (см. Выше).

Окончательное редактирование: проблема решена путем правильного неправильного размещения достаточно места для данных узла. Спасибо тем, кто помог. В моем коде есть другие проблемы, но они лучше всего подходят для другого вопроса и для другого фрагмента кода.

1 Ответ

1 голос
/ 12 августа 2011

Несколько вещей:

Как уже было сказано, list->size = sizeof(list);, вероятно, не делает то, что вы думаете

Передаваемый в качестве аргумента * 1006, вероятно, является вашей основной проблемой и кажется опасным (что это за значение переменной при вызове функции?)

Выполнение dlnode_t * newnode = safe_malloc(size); с неправильным размером может объяснить вашу проблему

dlnode_t * newnode = safe_malloc(size);

вероятно, следует заменить на

dlnode_t * newnode = safe_malloc(sizeof(dlnode_t));

Последнее, в вашем списке, вы используете void *value напрямую, а не его копию. Так что если вы не вызываете эту функцию всегда в одном и том же блоке, у вас будут проблемы

С той же сигнатурой функции, я думаю, параметр size должен представлять размер параметра value, чтобы сделать его malloc / memset и сохранить его в вашем списке

...