未初始化的内存在我的单链表实现中
我试图在c中实现一个单独链接的链表。 我希望能够使用列表的多个实例,并且我想在主函数中创建列表。 这就是为什么我选择以我的方式实施它。
代码工作得很好,但由于输出valgrind创建,我很担心。 此外,我尝试在嵌入式系统的项目中使用代码,并发生奇怪的错误。
valgrind输出是:
开始...
== 3570 ==条件跳转或移动取决于未初始化的值(s)
== 3570 == 0x100000E8E:push_cfront(在./map_test中)
== 3570 == by 0x100000D4F:main(在./map_test中)
== 3570 ==未初始化的值是由堆分配创建的
== 3570 == at 0x100008EBB:malloc(在/usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so中)
== 3570 == by 0x100000E80:push_cfront(在./map_test中)
== 3570 == by 0x100000D4F:main(在./map_test中)
== == 3570
...完成
它也告诉我,我失去了一个街区。 我在哪里解决它的错误
== 3570 ==泄漏摘要:
== 3570 ==绝对丢失:1个块中的16个字节
== 3570 ==间接丢失:0个字节0个字节
== 3570 ==可能丢失:1块中2,064个字节
== 3570 ==仍然可以访问:0个字节的0个字节
== 3570 ==抑制:186块中的24,525字节
请给我一个提示我出错的地方。
test.c的:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "command_list.h"
int main() {
printf("starting...n");
Clist * command_list = malloc(sizeof(Clist));
if (command_list == NULL) printf("Malloc Failedn");
command_list->head = NULL;
//push_cback(command_list, 0);
push_cfront(command_list,1);
free_clist(command_list);
free(command_list);
printf("n...finishedn");
return 0;
}
command_list.h:
#ifndef __COMMAND_LIST_H
#define __COMMAND_LIST_H
typedef struct cnode {
uint8_t command;
struct cnode * next;
} Cnode;
typedef struct clist {
Cnode * head;
} Clist;
void push_cback(Clist * list, uint8_t command);
void push_cfront(Clist * list, uint8_t command);
void free_clist(Clist * list);
#endif
command_list.c
void push_cfront(Clist * list, uint8_t command){
Cnode * new_node;
new_node = malloc(sizeof(Cnode));
if (new_node->next == NULL) {
return;
}
new_node->command = command;
new_node->next = list->head;
list->head = new_node;
}
void free_clist(Clist * list){
if (list->head == NULL){
return; //already empty
}
Cnode * current = list->head;
while (current->next != NULL){
Cnode* temp = current->next;
free(current);
current = temp;
}
free(current);
list->head = NULL;
}
你有几个问题。 您正在检查new_node->next
( new_node->next
内存中的未初始化数据)而不是new_node
(malloc的返回值)。 在我的电脑上,至少这也会导致内存不能被释放,因为偶然new_node->next
是null,所以你返回时没有释放new_node
。 另外,如果你想支持推送到链表的后面,你应该考虑一个循环链表,因为它允许该操作而不必遍历整个事物。
最后,一些技巧:使用valgrind是很好的,但如果使用-g
编译来启用调试符号,它会更有帮助,因此valgrind会告诉您行号。 另外,当我创建链表时,我喜欢使用虚拟头节点来进行某些操作,以避免出现空列表或单例列表的特殊情况。 为了插入到已排序的链接列表中,该技术如下所示:
int sorted_insert(Clist *list, char new_command){
Cnode _head = {NULL, list->head}, *head = &_head, *prev = head, *tmp;//head is an auto dummy node obviating null checks.
int ord = -1;//If there are no existing nodes, newObj would be less than all objects.
while(prev->next && (ord = (int)newObj - prev->next->command)) > 0){//Iterate by prev->next not curr to use only one pointer.
prev = prev->next;//Looping while there is a next node and its data compares less than new_command.
}
if((!ord) || !(tmp = malloc(sizeof(Cnode))){//newObj is already in the list or allocation failed.
return 0;
}
*tmp = (Cnode){.next=prev->next, .command=new_command};
prev->next = tmp;
list->head = head->next;//un- add head which is then deallocated by stack frame cleanup.
return 1;
}
当你检查它的值时, new_node->next
是未初始化的。 你不需要那个。
如果您查找malloc
失败,请为malloc
设置返回码并在调用时检查它。
在此之前,不需要push_cfront
的if
分支。
...或者你想检查list->head
而不是?
此外, push_cfront
这段代码也有问题
new_node = malloc(sizeof(Cnode));
if (new_node->next == NULL) {
return;
}
由于new_node
内存未初始化,因此它是未定义的行为。 您可能想检查if (new_node == NULL)
查看内存是否实际分配。
上一篇: uninitialised memory in my singly linked list implementation