我正在编写一个名为Process的非常简单的结构,代码似乎在快速浏览时正确实现,但是在测试我的代码时,它似乎一直在崩溃程序,无论是sysMalloc断言失败还是双重free()错误一个人试图释放它。
一些相关代码:
声明
typedef struct Process{
int pid;
int background;
int group;
int status;
char* name = 0;
} Process;
构造
Process* Process_init(char* name, int pid, int group, int background){
Process* output = (Process*)calloc(1, sizeof(Process*));
output->name = name;
output->pid = pid;
output->group = group;
output->background = background;
output->status = 0;
return output;
}
致电代码
char* command = "python";
char* command1= "cat < testing";
Process* proc = Process_init("command", 1, 1, 1);
Process* proc2 = Process_init("command1", 1, 1, 1);
有一些奇怪的行为,它似乎第一次工作,但在第二次调用时导致sysMalloc错误(这就是我称之为两次的原因。)
我尝试使用Valgrind,它给了我以下内容:
invalid write of size 4
==3485== at 0x8049A03: Process_init (process.c:6)
==3485== by 0x80488C2: main (test.c:58)
==3485== Address 0x419e730 is 12 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488C2: main (test.c:58)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A14: Process_init (process.c:8)
==3485== by 0x80488C2: main (test.c:58)
==3485== Address 0x419e728 is 4 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488C2: main (test.c:58)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A1D: Process_init (process.c:9)
==3485== by 0x80488C2: main (test.c:58)
==3485== Address 0x419e724 is 0 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488C2: main (test.c:58)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A23: Process_init (process.c:10)
==3485== by 0x80488C2: main (test.c:58)
==3485== Address 0x419e72c is 8 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488C2: main (test.c:58)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A03: Process_init (process.c:6)
==3485== by 0x80488EA: main (test.c:59)
==3485== Address 0x419e768 is 12 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488EA: main (test.c:59)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A14: Process_init (process.c:8)
==3485== by 0x80488EA: main (test.c:59)
==3485== Address 0x419e760 is 4 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488EA: main (test.c:59)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A1D: Process_init (process.c:9)
==3485== by 0x80488EA: main (test.c:59)
==3485== Address 0x419e75c is 0 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488EA: main (test.c:59)
==3485==
==3485== Invalid write of size 4
==3485== at 0x8049A23: Process_init (process.c:10)
==3485== by 0x80488EA: main (test.c:59)
==3485== Address 0x419e764 is 8 bytes after a block of size 4 alloc'd
==3485== at 0x402425F: calloc (vg_replace_malloc.c:467)
==3485== by 0x80499F9: Process_init (process.c:5)
==3485== by 0x80488EA: main (test.c:59)
--Snip--
所以,看起来问题出现在构造函数中,但我不确定为什么会这样,因为它看起来像是一个非常直接的变量。
答案 0 :(得分:3)
Process* output = (Process*)calloc(1, sizeof(Process*));
不正确。您只为指针(4或8字节)分配足够的内存。
正确的代码:
Process* output = calloc(1, sizeof(*output));
改进:
output
个点分配了足够的字节,这是一个Process
,而不是只有指针到Process
的足够字节。sizeof(*output)
,我们删除了对类型名称(DRY)的附加引用,这可以确保您的代码正确无误,即使有人更改了output
指向的类型,并忘记改变其余部分。calloc
的结果是removed the cast。 calloc
返回void*
,可以在没有强制转换的情况下将其分配给任何指针类型变量。此外,您应该检查任何函数的返回值,特别是返回内存的函数:
Process* Process_init(char* name, int pid, int group, int background){
Process* output = calloc(1, sizeof(*output));
if (output == NULL)
return NULL;
output->name = name;
output->pid = pid;
output->group = group;
output->background = background;
output->status = 0;
return output;
}
此函数的任何使用者也应检查其返回值。