在用C设计游戏实体系统时,我尝试了一个"等于免费的"初始化方法。我很惊讶地发现linter告诉我在init函数结束时发生了内存泄漏,并且我的变量ent
从未在以下代码中初始化。事实证明这是正确的,因为我得到了一个"总线错误":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent = malloc(sizeof(*ent));
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
我想到上面的代码会做什么,是把我提供的空ent
指针作为参数,告诉它指向一些新分配的内存,然后填写那个内存一切都会好的。我不知道它真正做了什么导致了一个&#34;总线错误&#34;我是否遗漏了一些关于指针和malloc的批评?
我依旧记得在某些C代码中看到与之前完全相似的东西(无等分结构初始化),我更倾向于使用类似于此的无等待初始化样式(破坏) )代码如果在C中可以做这样的事情。
答案 0 :(得分:4)
将malloc
调用移出初始化函数:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent = malloc(sizeof(*ent))))
return 1;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
您将指向已分配块的指针指定给局部变量(ent)。这不会影响ent
中的main
。
如果您希望将malloc
保留在entity_init
中,则应使用双指针,但您还应更改签名以允许从{malloc
发出失败信号entity_init
{1}}
int entity_init(entity_t **ent, int _x, int _y)
{
if(NULL==(*ent = malloc(sizeof(**ent))))
return -1;
(*ent)->x = _x;
(*ent)->y = _y;
}
int main(void)
{
entity_t* ent;
if(0>entity_init(&ent, 10, 24))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
更常见的模式是:
entity_t *entity_new(int _x, int _y)
{
entity_t *ent = malloc(sizeof(*ent));
if (NULL==ent)
return NULL;
ent->x = _x;
ent->y = _y;
return ent;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent=entity_new(10,24)))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
答案 1 :(得分:1)
如果必须在entity_init()
函数内进行分配,则需要返回指向分配的指针,或者通过使ent
指向指向entity_t
的指针来添加间接层。 。在发布的代码中,entity_init()
ent
内是传递给函数的指针的副本。对该指针所做的任何更改(例如将指定内存分配的地址分配给指针)都不会从调用函数中看到,因为在该函数返回后该副本将不再存在。
另请注意,您需要检查malloc()
返回的值,以确保分配成功。如果成功,该功能可以继续初始化过程;如果没有,ent
可以保留一个空指针,应该在调用函数中检查:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t **ent, int _x, int _y)
{
*ent = malloc(sizeof **ent);
if (*ent) {
(*ent)->x = _x;
(*ent)->y = _y;
}
}
int main(void)
{
entity_t *ent;
entity_init(&ent, 10, 24);
if (ent == NULL) {
fprintf(stderr, "Allocation failure in entity_init()\n");
exit(EXIT_FAILURE);
}
printf("Entity: x%d y%d\n", ent->x, ent->y);
return 0;
}
节目输出:
Entity: x10 y24
答案 2 :(得分:-1)
正如Weather Vane指出的那样,malloc会覆盖你传入本地范围内函数的指针,但是指针是按值传递的,所以你不能把它取回来。从init
返回后,内存将丢失。
尝试这样的事情:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t** ent, int _x, int _y)
{
*ent = malloc(sizeof(entity_t *));
*(ent)->x = _x;
*(ent)->y = _y;
}
int main(void)
{
entity_t* ent;
entity_init(&ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}