【问题标题】:How to fix my C Circular List Double Free Error如何修复我的 C 循环列表双重免费错误
【发布时间】:2021-10-03 22:36:33
【问题描述】:

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

#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



【问题讨论】:

  • 在查看您的代码之前,任何循环链表都不会有任何空值,如果它有项目(除非它有一个哨兵。)你确定你没有用非覆盖值吗? -空值?通常你会记住一个节点并测试next 值是否就是那个节点。
  • 我当然将结构列表初始化为 null,然后在输入它们时覆盖这些值。然后我遇到的问题是当我释放这些值时检查它们是否为空。我可以用常规的 LinkedList 做到这一点,这里有什么不同吗?这样的检查是不可能的吗?
  • 如果你抽出一个例子,你会发现next在循环链表中没有一个是空的;因此,您必须在第二次第一个指针是当前指针时结束,而不是在 null 时结束。
  • 对。因此,我不会检查 NULL,而是检查 *list == (*list) ->next 是否会检查。尽管那不会让我访问列表的最后一个元素。如果我输入a和b在哪里。我可以删除 a 但无法删除 b。

标签: c circular-list


【解决方案1】:

空循环列表是一种特殊情况。在insertion 中,您已将边界空值解释为非空值。但是,在removal 中,当从非空移动到空时。 (由于一个非空的格式良好的循环链表,它的next都不是空的,所以删除冗余代码。)

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    相关资源
    最近更新 更多