c语言链表的意外修改

问题描述 投票:0回答:1
#include <stdio.h>
#include <stdlib.h>

// 定义DocNode结构
struct DocNode {
    int doc_id;
    struct DocNode* next;
};

// 创建新的节点
struct DocNode* create_node(int doc_id) {
    struct DocNode* new_node = (struct DocNode*)malloc(sizeof(struct DocNode));
    new_node->doc_id = doc_id;
    new_node->next = NULL;
    return new_node;
}

int main() {
    // 定义doc_lists数组,假设有两个链表
    int query_count = 2;
    struct DocNode* doc_lists[2];

    // 初始化第一个链表: 338216 -> 338217 -> 379830
    doc_lists[0] = create_node(338216);
    doc_lists[0]->next = create_node(338217);
    doc_lists[0]->next->next = create_node(379830);

    // 初始化第二个链表: 123456 -> 789012
    doc_lists[1] = create_node(123456);
    doc_lists[1]->next = create_node(789012);

    // 输出每个链表的内容
    for (int i = 0; i < query_count; i++) {
        printf("doc[%d] is: ", i);
        struct DocNode* doc_list = doc_lists[i];
        while (doc_list) {
            printf("%d ", doc_list->doc_id);
            doc_list = doc_list->next;
        }
        printf("\n");
    }

    // 遍历并释放链表1中的节点
    struct DocNode* temp_result = doc_lists[0];
    printf("\nReleasing temp_result:\n");
    while (temp_result) {
        struct DocNode* temp = temp_result;
        temp_result = temp_result->next;
        printf("%d ", temp->doc_id);
        free(temp);
    }
    printf("\n");

    // 再次尝试输出链表内容
    printf("\nTo check the result:\n");
    for (int i = 0; i < query_count; i++) {
        printf("doc[%d] is: ", i);
        struct DocNode* doc_list = doc_lists[i];
        while (doc_list) {
            printf("%d ", doc_list->doc_id);
            doc_list = doc_list->next;
        }
        printf("\n");
    }

    return 0;
}

上面的代码主要分为三个部分:

  1. 输出doc_list[0]:结果doc[0]为:338216 338217 379830
  2. 赋值*temp_result = doc_list[0]:输出temp_result的各个节点。结果是338216 338217 379830,使用free(temp_result)释放temp_result的每个节点。
  3. 再次输出doc_list[0]:结果doc[0]为:0 3

在上面代码的最后一个for循环中,如果使用free(temp)释放doc_list[0],则会出现double free错误。但是,如果不使用 free(temp) 来释放 doc_list[0],则多次运行代码会导致分段错误。怀疑是链表被误用了,但是目前还不清楚为什么最终输出的是 doc[0] is:0 3 而不是随机值。

可能原因:问题是否与深度复制有关? (根据相关内容,深复制似乎需要实现自定义功能。但是,在涉及大量数据的情况下,有人担心深复制可能会影响性能。)

我是电脑初学者,第一次提问,请见谅,衷心感谢

最后一题没有通过,我又改了一遍(现在我放入了修改后的最小运行代码),现在的问题是,我想用一个*temp_list=doc_list[0],但是我后续的操作会删除一些temp_list[0] 的内容,这导致 doc_list[0] 的部分内容似乎因某种原因被修改。对此我能做什么?

查看了相关材料,其中提出了此类情况下分段错误的潜在解决方案,例如“创建时将指针初始化为 NULL”和“调用 free() 后将指针设置为 NULL”。然而,这些解决方案并没有解决问题。

c pointers memory-management deep-copy double-free
1个回答
0
投票

在此代码块中:

struct DocNode* temp_result = doc_lists[0];
printf("\nReleasing temp_result:\n");
while (temp_result) {
    struct DocNode* temp = temp_result;
    temp_result = temp_result->next;
    printf("%d ", temp->doc_id);
    free(temp);
}

您释放了

doc_lists[0]
持有的链表,但是 您从未设置过
doc_lists[0] = NULL

因此,在下一个代码块中,您使用指向已释放对象的指针。

© www.soinside.com 2019 - 2024. All rights reserved.