如何修复我的C循环列表双自由错误



我在修复与循环列表代码相关的内存泄漏时遇到了麻烦。任何帮助将不胜感激!我可以使用帮助确定如何修复有问题的内存泄漏。当然,这与双重释放代码有关,这是问题所在。然而,我提供了一个空指针检查,被我的代码完全忽略,有什么我可以做这里来解决这个问题吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char value;
struct node* next;
};
void insertion(struct node** list);
void removal(struct node** list);
int main() {
char userInput;
struct node* list = NULL;
printf("Enter "i" to insert a new element, "r" to remove an element, "q" to quit: ");
while (scanf(" %c", &userInput) == 1) { 
if (userInput == 'q') {
break;
}
else if (userInput == 'i') {
printf("Enter character to be enqueued (inserted): ");
insertion(&list);
}
else if (userInput == 'r') {
removal(&list);
}
printf("Enter "i" to insert a new element, "r" to remove an element, "q" to quit: ");
}

return 0;
}
void insertion(struct node** list) {
char userInput;
struct node* newNode;
newNode = (struct node*)malloc(sizeof(struct node));
scanf(" %c", &userInput);

if (*list == NULL) {
newNode->value = userInput;
newNode->next = newNode;
*list = newNode;
} 
else {
newNode->value = userInput;
newNode->next = (*list)->next;
(*list)->next = newNode;
*list = newNode;
}
}
void removal(struct node** list)
{
struct node* temp;
if (*list == NULL || strlen(*list) == NULL)
printf("List is empty.n");

else if(*list != NULL){
temp = (*list)->next;  
(*list)->next = temp->next;
printf("%c", *list);
if ((*list)->next == NULL) {
*list = NULL;
return;
}
printf("The character removed was an "%c" n", temp->value);
free(temp);
}
}
a.out
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: i
Enter character to be enqueued (inserted): a
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: r
The character removed was an "a"
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: r
List is empty.
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: i
Enter character to be enqueued (inserted): a
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: i
Enter character to be enqueued (inserted): b
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: i
Enter character to be enqueued (inserted): c
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: r
PThe character removed was an "a"
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: r
PThe character removed was an "b"
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: r
PThe character removed was an "c"
Enter "i" to insert a new element, "r" to remove an element, "q" to quit: r
PThe character removed was an " "
*** Error in `a.out': double free or corruption (fasttop): 0x0000000001fb1050 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x9a749)[0x7ff38e49c749]
a.out[0x4008fa]
a.out[0x400771]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7ff38e43bd45]
a.out[0x400649]
======= Memory map: ========
00400000-00401000 r-xp 00000000 00:2d 313533460                          /home/students/connelg2/Code315/a.out
00600000-00601000 r--p 00000000 00:2d 313533460                          /home/students/connelg2/Code315/a.out
00601000-00602000 rw-p 00001000 00:2d 313533460                          /home/students/connelg2/Code315/a.out
01fb1000-01fd2000 rw-p 00000000 00:00 0                                  [heap]
7ff288000000-7ff288021000 rw-p 00000000 00:00 0
7ff288021000-7ff28c000000 ---p 00000000 00:00 0
7ff28e39d000-7ff28e3b2000 r-xp 00000000 fc:00 8855075                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ff28e3b2000-7ff28e5b1000 ---p 00015000 fc:00 8855075                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ff28e5b1000-7ff28e5b2000 r--p 00014000 fc:00 8855075                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ff28e5b2000-7ff28e5b3000 rw-p 00015000 fc:00 8855075                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ff28e5b3000-7ff28e5b4000 r-xp 00216000 fc:00 8855075                    /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7ff28e5b4000-7ff28e5d7000 r-xp 00000000 fc:00 9172916                    /usr/lib64/ld-2.17.so
7ff28e7be000-7ff28e7c1000 rw-p 00000000 00:00 0
7ff28e7d2000-7ff28e7d6000 rw-p 00000000 00:00 0
7ff28e7d6000-7ff28e7d7000 r--p 00022000 fc:00 9172916                    /usr/lib64/ld-2.17.so
7ff28e7d7000-7ff28e7d8000 rw-p 00023000 fc:00 9172916                    /usr/lib64/ld-2.17.so
7ff28e7d8000-7ff28e7d9000 rw-p 00000000 00:00 0
7ff38e1fd000-7ff38e200000 r-xp 00000000 fc:00 8429031                    /usr/lib64/libksplice_helper.so
7ff38e200000-7ff38e3ff000 ---p 00003000 fc:00 8429031                    /usr/lib64/libksplice_helper.so
7ff38e3ff000-7ff38e400000 r--p 00002000 fc:00 8429031                    /usr/lib64/libksplice_helper.so
7ff38e400000-7ff38e401000 rw-p 00000000 00:00 0
7ff38e401000-7ff38e402000 r-xp 00204000 fc:00 8429031                    /usr/lib64/libksplice_helper.so
7ff38e402000-7ff38e5c7000 r-xp 00000000 fc:00 9019623                    /usr/lib64/libc-2.17.so
7ff38e5c7000-7ff38e7c7000 ---p 001c5000 fc:00 9019623                    /usr/lib64/libc-2.17.so
7ff38e7c7000-7ff38e7cc000 r--p 001c5000 fc:00 9019623                    /usr/lib64/libc-2.17.so
7ff38e7cc000-7ff38e7ce000 rw-p 001ca000 fc:00 9019623                    /usr/lib64/libc-2.17.so
7ff38e7ce000-7ff38e7d3000 rw-p 00000000 00:00 0
7ff38e7d3000-7ff38e7d4000 r-xp 003d1000 fc:00 9019623                    /usr/lib64/libc-2.17.so
7ffd2ac61000-7ffd2ac82000 rw-p 00000000 00:00 0                          [stack]
7ffd2ad4a000-7ffd2ad4d000 r--p 00000000 00:00 0                          [vvar]
7ffd2ad4d000-7ffd2ad4f000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

空循环列表是一种特殊情况。在insertion中,你已经考虑了从零到非零的边界。然而,在removal中,当从非空移动到空时。(因为一个结构良好的循环链表不是空的,它的next都不是空的,所以删除冗余代码。)

if(*list != NULL) {
temp = (*list)->next;  
(*list)->next = temp->next;
free(temp);
}

如果列表大小为1,则temp == *list。你free(temp),现在你指向一个无效的内存位置,因为temp == *list。一种解决方案是检查temp == temp->next(大小为1,),如果是,设置*list = NULL(大小为0)