gpt4 book ai didi

c - 为什么 Valgrind 会提示这段代码?

转载 作者:太空宇宙 更新时间:2023-11-04 06:12:47 25 4
gpt4 key购买 nike

我正在尝试实现一个存储非负整数的链表。我的实现如下所示:

我对内存泄漏很好奇,所以我使用命令“valgrind --leak-check=yes”试用了这个名为 Valgrind 的工具。

==2540== error calling PR_SET_PTRACER, vgdb might block
==2540== Invalid write of size 4
==2540== at 0x10875E: node_create (in LinkedList/bin/main)
==2540== by 0x108832: list_append (in LinkedList/bin/main)
==2540== by 0x108920: main (in LinkedList/bin/main)
==2540== Address 0x522d098 is 0 bytes after a block of size 8 alloc'd
==2540== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2540== by 0x10874B: node_create (in LinkedList/bin/main)
==2540== by 0x108832: list_append (in LinkedList/bin/main)
==2540== by 0x108920: main (in LinkedList/bin/main)
.
.
.
==2540== Invalid read of size 4
==2540== at 0x1088BA: list_pop (in LinkedList/bin/main)
==2540== by 0x1089E1: main (in LinkedList/bin/main)
==2540== Address 0x522d138 is 0 bytes after a block of size 8 alloc'd
==2540== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2540== by 0x10874B: node_create (in LinkedList/bin/main)
==2540== by 0x108832: list_append (in LinkedList/bin/main)
==2540== by 0x108942: main (in LinkedList/bin/main)
.
.
.
==2540== HEAP SUMMARY:
==2540== in use at exit: 0 bytes in 0 blocks
==2540== total heap usage: 10 allocs, 10 frees, 584 bytes allocated
==2540==
==2540== All heap blocks were freed -- no leaks are possible

相应的功能是这样实现的:

struct Node {
struct Node* next;
int value;
};

struct List {
struct Node* head;
};

typedef struct Node* Node;
typedef struct List* List;

Node node_create(int value, Node nextNode) {
if(value < 0) {
printf("Error: Could not create node, value is negative.\n");
return NULL;
}

Node node = malloc(sizeof(Node));
if(node != NULL)
{
node->value = value;
node->next = nextNode;
} else {
printf("Error: Could not create node, malloc returned NULL.\n");
}

return node;
}

int list_append(List listHandle, int value) {
Node current = listHandle->head;
Node new = node_create(value, NULL);

if(new == NULL) {
return -1;
}

if(current == NULL) {
listHandle->head = new;
} else {
while(current->next != NULL) {
current = current->next;
}
current->next = new;
}

return value;
}

int list_pop(List listHandle) {
if(listHandle->head == NULL) {
printf("Error: Trying to pop an empty list.\n");
return -1;
}

Node temp = listHandle->head;
int value = temp->value;

if(temp->next == NULL)
{
listHandle->head = NULL;
} else {
listHandle->head = temp->next;
}

free(temp);
return value;
}

我做错了什么?我怎样才能改进代码?这甚至是一个问题还是 Valgrind 只是过于迂腐?

最佳答案

typedef struct Node* Node;

Node node = malloc(sizeof(Node));

这将分配 sizeof(Node) == sizeof(struct Node*) 字节的内存。所以 Node node 不指向 sizeof(struct Node) 字节的内存。您最终会遇到越界/无效的内存访问。

要修复您的代码,取消引用指向结构节点的指针或隐式使用带有 sizeof 的结构节点:

Node node = malloc(sizeof(*node));
Node node = malloc(sizeof(struct Node));

这只是一个修复。它使您的代码更加困惑,并且您刚刚发现为什么隐藏在 typedef 后面的指针不是一个好主意。线路:

Node node = malloc(sizeof(*Node));

将不起作用,因为 Node 命名了一个类型,不能取消引用,正如@Ctx 在评论中指出的那样。

我个人强烈建议重写所有代码以使用:

 typedef struct Node Node;

Node *node_create(int value, Node *nextNode) {
...
Node *node = malloc(sizeof(Node));
...
}

现在,任何立即查看函数 node_create 的程序员都会知道,它返回指向某些数据的指针,可能是动态分配的。 Is 更具可读性并且不隐藏指针赋值。

关于c - 为什么 Valgrind 会提示这段代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52919979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com