gcc 4.5.1 c89
我已经编写了这个源代码,以便我更好地理解malloc和calloc。
我理解,但只是有几个问题。
dev = malloc(number * sizeof *devices);
等于此calloc。我并不担心清理记忆。
dev = calloc(number, sizeof *devices);
与在while循环中执行5次相比,究竟是什么呢?
dev = malloc(sizeof *devices);
我猜第一个和第二个是创建一个指向5结构设备的指针。第三个是创建一个指向结构设备的指针?
我的程序说明了使用valgrind编译和运行的3种不同方法--leak-check = full。
非常感谢您的任何建议。
#include <stdio.h>
#include <stdlib.h>
struct Devices {
#define MAX_NAME_SIZE 80
size_t id;
char name[MAX_NAME_SIZE];
};
struct Devices* create_device(struct Devices *dev);
void destroy_device(struct Devices *dev);
int main(void)
{
size_t num_devices = 5;
size_t i = 0;
struct Devices *device = NULL;
struct Devices *dev_malloc = NULL;
struct Devices *dev_calloc = NULL;
for(i = 0; i < num_devices; i++) {
device = create_device(device);
/* Assign values */
device->id = i + 1;
sprintf(device->name, "Device%zu", device->id);
/* Print values */
printf("ID ----- [ %zu ]\n", device->id);
printf("Name --- [ %s ]\n", device->name);
/* Test free */
destroy_device(device);
}
printf("\n");
dev_malloc = malloc(num_devices * sizeof *dev_malloc);
for(i = 0; i < num_devices; i++) {
/* Assign values */
dev_malloc->id = i + 1;
sprintf(dev_malloc->name, "dev_malloc%zu", dev_malloc->id);
/* Print values */
printf("ID ----- [ %zu ]\n", dev_malloc->id);
printf("Name --- [ %s ]\n", dev_malloc->name);
}
/* Test free */
destroy_device(dev_malloc);
printf("\n");
dev_calloc = calloc(num_devices, sizeof *dev_calloc);
for(i = 0; i < num_devices; i++) {
/* Assign values */
dev_calloc->id = i + 1;
sprintf(dev_calloc->name, "dev_calloc%zu", dev_calloc->id);
/* Print values */
printf("ID ----- [ %zu ]\n", dev_calloc->id);
printf("Name --- [ %s ]\n", dev_calloc->name);
}
/* Test free */
destroy_device(dev_calloc);
return 0;
}
struct Devices* create_device(struct Devices *dev)
{
/* Not checking for memory error - just simple test */
return dev = malloc(sizeof *dev);
}
void destroy_device(struct Devices *dev)
{
if(dev != NULL) {
free(dev);
}
}
答案 0 :(得分:5)
calloc(a,b)
和malloc(a*b)
是等效的,除了算术溢出或类型问题的可能性,以及calloc
确保内存是零字节填充的事实。分配的内存可用于a
个元素数组,每个元素的大小为b
(反之亦然)。另一方面,调用malloc(b)
a
次会产生a
个大小为b
的单个对象,这些对象可以独立释放,而不是在一个数组中(虽然你可以将它们的地址存储在一个指针数组中)。
希望这有帮助。
答案 1 :(得分:4)
malloc(n)分配n个字节加上填充和开销。
calloc(m,n)分配m * n个字节加上填充和开销,然后将内存为零。
就是这样。
答案 2 :(得分:2)
前两个在连续内存中创建一个包含5个设备的数组。完成五次的最后一次malloc将创建5个单独的设备,这些设备不能保证在连续的内存中。
答案 3 :(得分:2)
已修改
第一个malloc(number * sizeof(*devices))
将分配足够的内存来存储number
个Device
。正如其他人所提到的,您可以将此块视为Device
的数组。你得到的指针将指向块的开头。
int number = 5;
Device *ptr = malloc(number * sizeof(*ptr));
/* stuff */
free(ptr);
使用calloc
的第二个做同样的事情,同时也将内存初始化为0.再次,您可以像对待Device
数组一样对待块。
int number = 5;
Device *ptr = calloc(number, sizeof(*ptr));
/* stuff */
free(ptr);
第三个循环5次,将产生5个不同的指针到5个不同的块,大到足以存储一个Device
。这也意味着5个指针中的每一个都必须单独free
。
Device *ptrs[5];
for(int i = 0; i < 5; ++i)
{
ptrs[i] = malloc(sizeof(*ptrs[i]));
}
/* stuff */
for(int i = 0; i < 5; ++i)
{
free(ptrs[i]);
}
答案 4 :(得分:1)
程序中的所有三个循环一次只使用一个struct Devices
个对象。后者分配额外的内存,好像它们将使用多个对象,但随后继续覆盖该内存的开头。如果在设置ID为2的对象后尝试使用ID为1的对象,则会发现不再有ID为1的对象。
相反,您可以执行类似这样的操作,将分配的内存视为结构数组:
dev_malloc = malloc(num_devices * sizeof *dev_malloc);
for (i=0; i<num_devices; i++) {
/* Assign values */
dev_malloc[i].id = i + 1;
sprintf(dev_malloc[i].name, "dev_malloc%zu", dev_malloc[i].id);
/* Print values */
printf("ID ----- [ %zu ]\n", dev_malloc[i].id);
printf("Name --- [ %s ]\n", dev_malloc[i].name);
}
free(dev_malloc);
答案 5 :(得分:1)
查看calloc的实现以查看差异。它可能是这样的:
// SIZE_MAX is defined in stdint.h from C99
void *calloc( size_t N, size_t S)
{
void *ret;
size_t NBYTES;
// check for overflow of size_t type
if (N > SIZE_MAX / S) return NULL;
NBYTES = N * S;
ret = malloc( NBYTES);
if (ret != NULL)
{
memset( ret, 0, NBYTES);
}
return ret;
}
答案 6 :(得分:0)
正如您所指出的那样,calloc
将内存分配为零,而malloc
则不分配。
你的例子1&amp; 2每个分配一个连续的五个结构块(并返回一个指向该块的指针),而示例3每个分配一个结构的五个独立的块(并给你五个彼此无关的指针。)