У меня проблема в двойном списке при программировании на Си.(Ошибка следующего указателя)

#c #linked-list #segmentation-fault #doubly-linked-list

#c #связанный список #ошибка сегментации #дважды связанный список

Вопрос:

 struct someEvent
{
    int id;
    int shouldRemove;
    struct someEvent *prev;
    struct someEvent *next;
} * someEvent;


struct someEvent *someEventQueue = NULL;


int main(){

struct someEvent **curr5 = amp;someEventQueue;
                while ((*curr5) != NULL)
                {
                    if ((*curr5)->shouldRemove == 1)
                    {
                        tmpflag = 1;
                        if ((*curr5)->prev == NULL amp;amp; (*curr5)->next == NULL)
                        {
                            (*curr5) = NULL;
                        }
                        else if ((*curr5)->prev == NULL)
                        {
                            (*curr5) = (*curr5)->next;
                            (*curr5)->prev = NULL;
                            //(*curr5)->prev->next = (*curr5)->next;
                        }
                        else if ((*curr5)->next == NULL)
                        {
                            (*curr5)->prev->next = NULL;
                        }
                        else
                        {
                            (*curr5)->prev->next = (*curr5)->next;
                            (*curr5)->next->prev = (*curr5)->prev;
                        }
                    }
                    if (tmpflag == 1)
                    {

                        break;
                    }

                    curr5 = amp;(*curr5)->next;
                }



  }
  

Я сделал свой код таким. Я хочу удалить узел, который должен быть перемещен равным 1.

введите описание изображения здесь

Эта картинка — someEventQueue . Я хочу удалить узел, идентификатор которого равен 2.

введите описание изображения здесь

Я хочу этот результат. Но в моем результате есть некоторые ошибки…

введите описание изображения здесь

Эта картинка является результатом моего кода. После отладки я обнаружил, почему у него ошибка. (*curr5)->prev->next = (*curr5)->next; эта часть отлично работает. Но после того, как эта часть (*curr5) будет изменена на (*curr5)->next и (*curr5)->next->prev = (*curr5)->prev; этот код вернет ошибку сегментации. Я не знаю, почему произошло такое изменение. Для решения этой проблемы я добавляю (*curr5)=(*curr5)->prev; между (*curr5)->prev->next = (*curr5)->next; и (*curr5)->next->prev = (*curr5)->prev; . Затем это завершается бесконечным циклом… Я думаю, что в моем коде нет ошибок, но я не знаю, почему (* curr5) изменяется после (*curr5)->prev->next = (*curr5)->next; . Мне нужен совет.

Комментарии:

1. Не связано, вы намеревались, чтобы этот код объявлял глобальную переменную someEvent типа struct someEvent * ? Если нет (т. Е. Если Вы вырезали typedef при вставке этого в SO), то прекратите скрывать указатели в typedef; это почти всегда плохая идея.

Ответ №1:

Вы делаете это более сложным, чем нужно. Похоже, что код хочет удалить первый узел в списке, для которого установлен shouldRemove флаг, а затем остановить. Управление узлами в двойных списках связано с двумя вещами:

  • указатель, который приведет вас туда.
  • узел, если таковой имеется, который содержит этот указатель.

Т.е.

 int main()
{
    struct someEvent **curr = amp;someEventQueue;
    struct someEvent *prev = NULL;

    while (*curr)
    {
        if ((*curr)->shouldRemove)
        {
            struct someEvent *tmp = *curr;
            *curr = tmp->next;
            if (tmp->next)
                tmp->next->prev = prev;

            // added to prevent memory leak. remove if these are
            //  maintained somewhere else.
            free(tmp);

            break;
        }
        else
        {
            prev = *curr;
            curr = amp;(*curr)->next;
        }
    }
}
  

Стоит отметить, что вы можете удалить все узлы с shouldRemove установленным флагом, удалив break; в приведенном выше цикле.