Я считаю, что ваша проблема заключается в вызове delete_list
в списках компонентов, которые вы передали своей функции merge_list
.
Если я правильно понимаю ваш код, list
на самом деле является просто указателем напервый узел связанного списка.Ваш create_list
выделяет узлы и возвращает адрес первого, который вы затем по какой-либо причине отбрасываете, что приводит к указателю на второй выделенный узел.
Примерно так:
list l = pointer to [1] -> [2] -> [3] ...
list m = pointer to [5] -> [10] -> [15] ...
Ваш merge_list
выполняет сортировку слиянием двух списков, , используя одинаковые узлы , изменяя указатели next / prev.
while(a&&b)
{
if(a->value<=b->value)
{
p->next = a;
a->prior=p;
p=a;
a=a->next;
Это означает, что указатель списка l
и указатель списка m
и указатель списка n
(объединенный список) указывают на одни и те же узлы.Когда вы делаете list n = merge_list(l,m)
, результат выглядит примерно так:
list n = pointer to [1] -> [2] -> [3] -> [5] -> [10] ...
list l = pointer to ^
list m = pointer to 5 ...................^
(указатели 'l' и 'm' не меняются, но узлы, на которые они указывают, изменяются функцией слияния.)
Когда вы попытаетесь free
перечислить узлы в вашей функции удаления, сработает первый вызов для удаления списка 'l'.Вызов для удаления списка «m» либо сразу завершится неудачей (если первый узел «m» был больше, чем первый узел «l», как в моем примере), либо освободит некоторые узлы, а затем завершится ошибкой.Удаление 'n' не удастся, так как все узлы, составляющие 'n', удаляются в вызовах для удаления 'l' и 'm'.
Это можно исправить несколькими способами.Самый простой - просто сбросить указатель списка l и m на NULL при вызове слияния, поскольку в вашей системе слияние двух списков «потребляет» их, и, следовательно, право собственности переходит от параметров к результату.
list n = merge_list(l, m); l = m = NULL;
Другим способом было бы создание функции слияния для создания дублирующихся узлов, что означает, что merge_list
фактически создаст копии двух списков, что позволит владельцу сохранять параметры владения параметрами.
list n = merge_list(l, m);
// now n, l, m, all exist and are separate
Окончательным решением было бы создание истинного объекта «списка», который находится между вызывающим и объектами узлов.Этот объект может быть изменен, чтобы отражать любую реальность, но он будет отдельным, и поэтому не будет перезаписан во время операций слияния и т. Д. (Я не рекомендую это, кстати. Это формально, но неэффективно.)