malloc和calloc之间的使用差异

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  #include  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 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 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 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); } } 

编辑清楚

  • 我想第一个和第二个是创建一个指向5结构设备的指针。 第三个是创建一个指向结构设备的指针?

第一个malloc(number * sizeof(*devices))将分配足够的内存来存储Devicenumber 。 正如其他人所提到的,您可以将此块视为一个Device数组。 你得到的指针将指向块的开头。

 int number = 5; Device *ptr = malloc(number * sizeof(*ptr)); /* stuff */ free(ptr); 

使用calloc的第二个做同样的事情,同时也将内存初始化为0.再次,你可以使用像块数组一样处理块。

 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]); } 

calloc(a,b)malloc(a*b)是等效的,除了算术溢出或类型问题的可能性,以及calloc确保内存是零字节填充的事实。 分配的内存可以用于每个大小为b a元素数组(反之亦然)。 另一方面,调用malloc(b) a将导致大小为b a单个对象可以独立释放并且不在数组中(尽管可以将它们的地址存储在指针数组中)。

希望这可以帮助。

malloc(n)分配n个字节加上填充和开销。

calloc(m,n)分配m * n个字节加上填充和开销,然后将内存归零。

而已。

前两个在连续内存中创建一个包含5个设备的数组。 完成五次的最后一个malloc将创建5个单独的设备,这些设备不能保证在连续的内存中。

程序中的所有三个循环一次只使用一个struct Devices对象。 后者分配额外的内存,好像他们将使用多个对象,但然后继续覆盖该内存的开头。 如果在设置ID为2的对象后尝试使用ID为1的对象,则会发现不再有ID为1的对象。

相反,你可以做这样的事情来将分配的内存视为结构数组:

 dev_malloc = malloc(num_devices * sizeof *dev_malloc); for (i=0; i 

查看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; } 

正如您所指出的, calloc将内存分配为零,而malloc则不分配。

您的示例1和2每个都分配一个由五个结构组成的连续块(​​并返回指向该块的指针),而示例3分别为每个一个结构分配五个独立的块(并为您提供五个彼此无关的指针)。