为什么在另一个函数中释放内存malloc()会导致崩溃?
我有一个结构和函数的链接列表,可以从中添加、删除和创建数据。现在,当我试图释放在create函数中分配的()数据时,问题就出现了。如果我删除了代码中释放内存的部分,但没有释放内存,那么程序就可以正常运行 结构:为什么在另一个函数中释放内存malloc()会导致崩溃?,c,linked-list,malloc,free,C,Linked List,Malloc,Free,我有一个结构和函数的链接列表,可以从中添加、删除和创建数据。现在,当我试图释放在create函数中分配的()数据时,问题就出现了。如果我删除了代码中释放内存的部分,但没有释放内存,那么程序就可以正常运行 结构: typedef struct carinfo_t { char * brand; char * model; int year; float value; struct carinfo_t * next; } carinfo_t; 创建要添加到列
typedef struct carinfo_t
{
char * brand;
char * model;
int year;
float value;
struct carinfo_t * next;
} carinfo_t;
创建要添加到列表中的项目的函数:
struct carinfo_t *createCarinfo(char *brand, char *model, int year, float value)
{
carinfo_t *newInfo = (carinfo_t *) malloc (sizeof(newInfo));
newInfo->brand = malloc (sizeof(brand));
newInfo->model = malloc (sizeof(model));
if (!newInfo)
{
printf("createCarinfo: error: no space left\n");
}
else
{
strcpy(newInfo->brand, brand);
strcpy(newInfo->model, model);
newInfo->year = year;
newInfo->value = value;
newInfo->next = NULL;
}
return newInfo;
}
自由功能:
void freeCarinfo(struct carinfo_t *carinfo)
{
if(carinfo->brand != 0)
{
free(carinfo->brand);
carinfo->brand = 0;
}
if(carinfo->model != 0)
{
free(carinfo->model);
carinfo->model = 0;
}
if(carinfo != 0)
{
free(carinfo);
carinfo = 0;
}
}
freeCarinfo()由我的removeCarinfo()函数调用,该函数基本上确保当我删除所查找的项目时,队列中的所有项目都正确匹配
我现在想做的是能够释放我给程序的内存
carinfo_t *newInfo = (carinfo_t *) malloc (sizeof(newInfo));
newInfo->brand = malloc (sizeof(brand));
newInfo->model = malloc (sizeof(model));
查看
sizeof()
运算符的返回值。我想你会发现你分配了足够的字节来存储指针,而不是结构或字符本身sizeof()
这样做很棘手
malloc()
实现很可能会为内部管理分配一些额外的字节。如果分配的内存太少,并且开始在这些内部结构上进行写操作,那么就完全进入了未定义的行为领域,这表明当您尝试free()
该块时,因为free()
可能会使用该数据
编辑:有关惯用的解决方案和@David Bowling的讨论,请参见下面的讨论,我将其推迟至:
carinfo\u t*newInfo=malloc(sizeof*newInfo)代码>首先,在为数据分配空间时,您犯了一个常见错误:
newInfo->brand = malloc (sizeof(brand));
这将分配足够的空间来存储指向char
的指针,而不是数据本身。然后尝试将数据复制到其中:
strcpy(newInfo->brand, brand);
这可能会写入比您为其创建的空间还多的数据
您需要为整个字符串以及\0
字符串结束标记创建足够的空间:
newInfo->brand = malloc (strlen(brand) + 1);
你也会在某个地方想要这个:
#include <string.h>
您可能需要的是:
carinfo_t *newInfo = malloc (sizeof(carinfo_t));
或者更好:
carinfo_t *newInfo = malloc (sizeof(*newInfo));
总之,这里有很多错误,这就是为什么你觉得它如此令人沮丧。重新阅读指针和动态分配,并根据所学内容重新审视代码。sizeof(brand)
并没有达到预期效果brand
是一个指针,因此可以得到指针的大小,4或8。newInfo=malloc(sizeof(newInfo))代码>已损坏newInfo
是一个指针。要获取“字符串”的长度,请使用strlen()
。还要注意,C字符串总是需要比其最大长度多一个字节。这是为了存储字符串的结束标记,即0
-terminator。学会使用sizeof
是一个运算符,而不是宏或函数。因此,括号()
不是它的一部分,在将它应用于变量时也不需要它。sizeof
不是宏。sizeof
的棘手之处在于它既不是宏也不是函数,而是一个通常在编译时产生结果的运算符,但有时会在运行时对其求值,并且通常(但并非总是)不会对其操作数求值。括号不是sizeof
运算符的一部分,而是操作数的一部分,操作数是一个表达式,可以是括号类型。你有OP遇到的问题的本质,有一个惯用的解决方案:carinfo\u t*newInfo=malloc(sizeof*newInfo)代码>。谢谢,@David Bowling,感谢你的启发。多年来,我一直在努力解决sizeof的棘手问题,确保只向它传递类型,这意味着代码将无法适应类型的变化,例如指针变量的变化,当我忘记在这两个地方更新类型时,会引入错误。当你这样写的时候,它看起来是不言而喻的,但我以前从未见过。这个习惯用法很有用,因为当类型在程序生命周期中发生变化时,只有左边的类型需要更新。因此,在程序维护中不容易出错,在初始编码中也不容易出错,因为程序员不必处理类型。请注意,这里的*newInfo
表达式不是由sizeof
计算的,而是由*newInfo
表达式的类型来确定大小。@melpomene感谢您为我丢失了该转换!非常感谢。我以前试过使用strlen(),但还是犯了同样的错误。可能是因为我不知道我没有为newInfo正确分配数据。再次感谢,不客气。你的方向绝对正确。你的目标是艰难的,但非常值得去做。继续走,你会到达那里的!将指针与值0
的整数常量进行比较与将指针与值NULL
进行比较的含义完全相同。两者都是与空指针常量的比较。如果其中一个被认为比另一个更传统,那么肯定会使用0
。另一方面,有一个很好的论据表明,出于文体的考虑,我更倾向于使用NULL
。@JohnBollinger是的,当我写这篇文章时,我意识到NULL
和0
不一样,但在编辑它的过程中丢失了这一点。谢谢你。就我而言,如果K&rv1在指针比较中使用NULL
(和),很难说0
更传统。我们是否应该在“对0
上的指针使用NULL
是当前最佳实践”这一点上妥协?
carinfo_t *newInfo = malloc (sizeof(*newInfo));