malloc和calloc之间的使用差异

时间:2010-11-30 17:40:59

标签: c 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 <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);
    }
}

7 个答案:

答案 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)

为清晰起见,

已修改

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

第一个malloc(number * sizeof(*devices))将分配足够的内存来存储numberDevice。正如其他人所提到的,您可以将此块视为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每个分配一个结构的五个独立的块(并给你五个彼此无关的指针。)