c - 如何修复我的 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
(尺寸一,),如果是,则设置*list = NULL
(尺寸为零。)
推荐阅读
- batch-file - 为什么在结帐后挂钩启动记事本后 TortoiseGit Git 命令进度对话框挂起?
- android - 轻导航栏问题
- reactjs - 在反应选择选项中使用枚举
- vue.js - 如何防止事件传播到父元素?@input.stop 不起作用。(NuxtJS)
- javascript - html按钮在点击时取消选择
- java - Azure Application Insights 代理日志 Java 线程名称
- javascript - Flask-SocketIO 和 SocketIO 客户端;客户端 Emit 事件不会持续触发
- firebase-authentication - 使用 Firebase 身份验证时获取 Google 刷新令牌
- api - 从 Google Hotels 获取酒店列表
- android - 带有 Google 助手和自定义 intent 名称的 Android 应用