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;
}

The code above has three main parts:

  1. Output doc_list[0]: The result is doc[0] is:338216 338217 379830
  2. Assign *temp_result = doc_list[0]: Output each node of temp_result. The result is 338216 338217 379830, and each node of temp_result is freed using free(temp_result).
  3. Output doc_list[0] again: The result is doc[0] is:0 3

In the last for loop of the code above, if free(temp) is used to release doc_list[0], a double free error occurs. However, if free(temp) is not used to release doc_list[0], running the code multiple times results in a segmentation fault. It is suspected that the linked list is being misused, but it is still unclear why the final output is doc[0] is:0 3 instead of random values.

Possible Cause: Is the issue related to deep copying? (Based on related content, deep copying seems to require implementing a custom function. However, there is concern that deep copying could impact performance in cases involving large amounts of data.)

I am a computer beginner, this is the first time to ask, please forgive me, and sincerely thank you

The last question did not pass, I changed it again (now I put in the modified minimum running code), now the problem is, I want to use a *temp_list=doc_list[0], but my subsequent operation will delete some of the content of temp_list[0], This causes parts of the doc_list[0] to seem to have been modified for some reason. What can I do about this?

Reviewed related materials, which suggest potential solutions for the segmentation fault in such cases, such as "initialize pointers to NULL when created" and "set the pointer to NULL after calling free()." However, these solutions did not resolve the issue.

2
  • 2
    Edit your question with a minimal reproducible example that demonstrates the problem. Commented Dec 12, 2024 at 4:58
  • 1
    My recommendation: rewrite using short functions that do one thing. print_list would be a good function name. free_list would be another one. Commented Dec 12, 2024 at 5:48

2 Answers 2

1

In this code block:

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);
}

you free the linked list held by doc_lists[0] but you never set doc_lists[0] = NULL.

So in the next code block when i is zero, you use a pointer to an object that was free'd.

One solution:

struct DocNode* temp_result = doc_lists[0];
doc_lists[0] = NULL; // <---------------- add this
printf("\nReleasing temp_result:\n");
answered Dec 12, 2024 at 6:13
Sign up to request clarification or add additional context in comments.

Comments

0

First notes:

  • Don't cast malloc, calloc, realloc in C.
  • Do check the return value from malloc to ensure it succeeded.
  • Creating an array of DocNode pointers then dynamically allocating nodes and linking them together into a list is very odd. This might be worth doing if you were declaring an array of DocNode structs to avoid the dynamic allocation, though.
  • query_count should be const.

None of these things stop your code from working, and it does compile free of warnings. Good job!

But, free does not have to set a pointer to NULL. as otherwise noted you're using a pointer which has been freed. This results in undefined behavior.

You may wish to modify your code to something like the following.

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

Sidenote:

Unless required as part of an academic exercise, in most situation where you need a dynamically sized collection, you probably would be better off with a dynamically resized array which provides O(1) random access and O(1) de-allocation.

answered Dec 12, 2024 at 6:18

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.