WedX - журнал о программировании и компьютерных науках

Зачем нам нужен list_for_each_safe() для удаления узлов в связанном списке ядра?

Я изучаю, как использовать API связанных списков ядра из list.h.

Я узнал, что мне нужно использовать list_for_each_safe() при удалении узлов с помощью list_del() вместо использования list_for_each().

Код для list_for_each_safe():

#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

Код для list_for_each():

    for (pos = (head)->next; pos != (head); pos = pos->next)

Я заметил, что они оба очень похожи, за исключением того, что версия _safe использует дополнительный аргумент для использования в качестве «временного хранилища» (указан здесь, list.h).

Я понимаю, когда правильно применять функцию, _safe версия для удаления, обычная версия для доступа, но мне любопытно, как дополнительный аргумент сделал ее «безопасной»?

Рассмотрим следующее, где я удаляю каждый узел в связанном списке, используя list_for_each_safe():

struct kool_list{
    int to;
    struct list_head list;
    int from;
    };

struct kool_list *tmp;
struct list_head *pos, *q;
struct kool_list mylist;

list_for_each_safe(pos, q, &mylist.list){
         tmp= list_entry(pos, struct kool_list, list);
         printf("freeing item to= %d from= %d\n", tmp->to, tmp->from);
         list_del(pos);
         free(tmp);
    }

Как предоставление q помогает в удалении?

Спасибо за любую помощь!


  • Я понял, никогда не думал, что это так прямолинейно, спасибо! 10.02.2012
  • q следовало бы назвать получше... что-то вроде pos_next. 03.09.2014

Ответы:


1

Это необходимо, потому что list_del внутренне изменяет значение pos полей. В вашем примере тело цикла даже освобождает память, занимаемую pos. Предположим, что вы будете использовать небезопасную версию цикла:

for (pos = (head)->next; pos != (head); pos = pos->next)

После выполнения тела цикла указатель pos становится недействительным, нарушая выражение приращения: pos = pos->next.

Напротив, безопасный foreach предварительно сохраняет значение pos->next во временной переменной, а затем обращается к последней вместо разыменования pos:

for (pos = (head)->next, n = pos->next; pos != (head); \
    pos = n, n = pos->next)
09.02.2012

2
pos = start;
del(pos);
pos = pos->next;

в отличие от

pos = start;
n = pos->next;
del(pos);
pos = n;

если del() является free() и memset(), pos->next не определено

09.02.2012
Новые материалы

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

ИИ в аэрокосмической отрасли
Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


Для любых предложений по сайту: [email protected]