英文:
Weird Memory Problem in Simply Linked-List Implementation C
问题
我正在编写一个包含元素结构{name, price}的简单链表(Simply Linked-List),在我实现的一些函数中出现了奇怪的行为。这些函数包括:
PopFront
(移除链表的第一个元素)PopByIndex
(根据给定的索引移除链表中的元素)
到底发生了什么事情?这些函数确实移除了它们应该移除的元素,但它们不知何故改变了另一个元素的价格值 😓。
示例:
在使用移除函数之前:
Name: A Price: 1.00
Name: B Price: 2.00
Name: C Price: 3.00
Name: D Price: 4.00
--------
|Menu|
--------
(1) Add Element in Front
(2) Add Element in Back
(3) Add Element in Position
(4) Remove Element from Front
(5) Remove Element from Back
(6) Remove Element by Position
(7) Print List
(8) Calculate Itens Sum
(0) Exit Program
在移除 D 元素之后,它将价格 A 的价格设为 0:
Name: A Price: 0.00
Name: B Price: 2.00
Name: C Price: 3.00
--------
|Menu|
--------
(1) Add Element in Front
(2) Add Element in Back
(3) Add Element in Position
(4) Remove Element from Front
(5) Remove Element from Back
(6) Remove Element by Position
(7) Print List
(8) Calculate Itens Sum
(0) Exit Program
我使用了GDB来查看元素确切何时被修改,发现是在调用free()
来释放被移除元素的内存地址时发生的。
最小可重现示例(Minimal Reproducible Example):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node Node;
typedef struct List List;
// 其他代码...
我已经提供了你的代码和问题的总结,没有进行额外的翻译。如果你有任何进一步的问题或需要进一步的帮助,请随时提问。
英文:
I am coding a Simply Linked-List that has a struct of elements composed by {name, price}, and in some of the function I'm implementing are presenting a weird behavior. These functions are:
PopFront
(That remove the last element of the list)PopByIndex
(That given an entry index, it will remove the element on that position)
What's happening exactly? Well, these functions do remove the element they are supposed to remove, but they somehow change the value of the price of another element of the list 😕.
Example:
Before use remove functions
Name: A Price: 1.00
Name: B Price: 2.00
Name: C Price: 3.00
Name: D Price: 4.00
--------
|Menu|
--------
(1) Add Element in Front
(2) Add Element in Back
(3) Add Element in Position
(4) Remove Element from Front
(5) Remove Element from Back
(6) Remove Element by Position
(7) Print List
(8) Calculate Itens Sum
(0) Exit Program
After remove D element it puts 0 to the price of A
Name: A Price: 0.00
Name: B Price: 2.00
Name: C Price: 3.00
--------
|Menu|
--------
(1) Add Element in Front
(2) Add Element in Back
(3) Add Element in Position
(4) Remove Element from Front
(5) Remove Element from Back
(6) Remove Element by Position
(7) Print List
(8) Calculate Itens Sum
(0) Exit Program
I used gdb to see what moment exactly, the element is modified and found that is when I call free()
to free the memory of the address of the element removed
Minimal Reproducible Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node Node;
typedef struct List List;
struct Node {
char name[100];
float price;
int code;
struct Node *prox;
};
struct List{
struct Node *head;
int size;
};
Node* InstantiateNode() {
Node *new_node = malloc(sizeof new_node);
new_node->prox = NULL;
return new_node;
}
void InitNode(Node *node, char *name, float price) {
strcpy(node->name, name);
node->price = price;
}
void PrintNode(Node node){
printf("Name: %8s Price: %.2f\n", node.name, node.price);
}
int EmptyList(List list) {
return list.size == 0 ? 1 : 0;
}
List *InstantiateList(void) {
List *new_list = malloc(sizeof new_list);
new_list->head = NULL;
new_list->size = 0;
return new_list;
}
void InitList(List *list, Node *new_node) {
new_node->prox = list->head;
list->head = new_node;
list->size++;
}
void PushFront(List *list, Node *new_node) {
if (EmptyList(*list)) {
InitList(list, new_node);
return;
}
Node *tracker = list->head;
while (tracker->prox != NULL)
tracker = tracker->prox;
tracker->prox = new_node;
list->size++;
}
void PushBack(List *list, Node *new_node) {
InitList(list, new_node);
}
Node *TrackListbyIndex(List lista, int index) {
if (index > lista.size) {
printf("Unreachable List index \n"); // Warning
return NULL;
}
int cont = 0;
Node *aux = lista.head;
while (cont != index) {
aux = aux->prox;
cont++;
}
return aux;
}
void PushByIndex(List *list, Node *new_node, int index) {
if (index == 0) {
PushBack(list, new_node);
return;
}
Node *aux = TrackListbyIndex(*list, index - 1);
Node *aux2 = aux->prox;
if (aux) {
new_node->prox = aux->prox;
aux->prox = new_node;
list->size++;
}
}
void PopFront(List *list) {
if (EmptyList(*list))
return;
Node* aux = list->head;
Node* tracker, *tracker_next;
tracker = list->head;
if (tracker->prox != NULL) {
tracker_next = tracker->prox;
while (tracker_next->prox != NULL) {
tracker = tracker_next;
tracker_next = tracker_next->prox;
}
tracker->prox = NULL;
aux = tracker_next;
}
if (aux == list->head) {
list->head = NULL;
}
free(aux);
list->size--;
}
void PopBack(List* list){
if(EmptyList(*list))
return;
Node* aux = list->head;
list->head = list->head->prox;
free(aux);
list->size--;
}
void PopByIndex (List *list, int index) {
if (index == 0) {
PopBack(list);
return;
}
//if (index + 1 == list->size) {
// PopFront(list);
// return;
//}
Node *aux, *aux_next;
aux = TrackListbyIndex(*list, index - 1);
if (aux) {
aux_next = aux->prox;
aux->prox = aux_next->prox;
free(aux_next);
list->size--;
}
}
void PrintList(List list) {
Node *tracker = list.head;
while (tracker != NULL) {
PrintNode(*tracker);
tracker = tracker->prox;
}
}
void Menu(void);
void HandleMenu(int);
int main(void) {
int option;
for (;;) {
Menu();
printf("Type your choosen:");
scanf("%d", &option);
system("clear");
HandleMenu(option);
}
return 0;
}
void Menu(void) {
printf("\t--------\n");
printf("\t |Menu|\n");
printf("\t--------\n");
printf("(1) Add Element in Front\n");
printf("(2) Add Element in Back\n");
printf("(3) Add Element in Position\n");
printf("(4) Remove Element from Front\n");
printf("(5) Remove Element from Back\n");
printf("(6) Remove Element by Position\n");
printf("(7) Print List\n");
printf("(8) Calculate Itens Sum\n");
printf("(0) Exit Program\n");
}
void HandleMenu(int option) {
static List *market_list = NULL;
Node* new_node = NULL;
char node_name[100];
float node_price;
int index;
if (market_list == NULL)
market_list = InstantiateList();
switch (option) {
case 0:
exit(1);
break;
case 1:
new_node = InstantiateNode();
printf("Type the product's name: ");
scanf(" %[^\n]", node_name);
printf("Type the product's price: ");
scanf("%f", &node_price);
InitNode(new_node, node_name, node_price);
PushFront(market_list, new_node);
printf("Item Added\n");
break;
case 2:
new_node = InstantiateNode();
printf("Type the product's name: ");
scanf(" %[^\n]", node_name);
printf("Type the product's price: ");
scanf("%f", &node_price);
InitNode(new_node, node_name, node_price);
PushBack(market_list, new_node);
printf("Item Added\n");
break;
case 3:
new_node = InstantiateNode();
printf("Type the product's name: ");
scanf(" %[^\n]", node_name);
printf("Type the product's price: ");
scanf("%f", &node_price);
InitNode(new_node, node_name, node_price);
printf("Type Index: ");
scanf("%d", &index);
PushByIndex(market_list, new_node, index-1);
printf("Item Added\n");
break;
case 4:
PopFront(market_list);
break;
case 5:
PopBack(market_list);
break;
case 6:
printf("Type Index: ");
scanf("%d", &index);
PopByIndex(market_list, index-1);
break;
case 7:
PrintList(*market_list);
break;
}
}
答案1
得分: 2
InstantiateNode()
分配了一个Node *
的空间,但您需要分配Node
的空间:
Node *new_node = malloc(sizeof *new_node);
InstantiateList()
分配了一个List *
的空间,但您需要分配List
的空间:
List *new_list = malloc(sizeof *new_list);
进行这两个更改后,移除后的输出如下:
名称: A 价格:1.00
名称: B 价格:2.00
名称: C 价格:3.00
英文:
InstantiateNode()
allocates space for aNode *
but you want space for theNode
:
Node *new_node = malloc(sizeof *new_node);
InstantiateList()
allocates space for aList *
but you want space for theList
:
List *new_list = malloc(sizeof *new_list);
After those two changes here is the output after the removal:
Name: A Price: 1.00
Name: B Price: 2.00
Name: C Price: 3.00
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论