malloc 和 calloc 的使用区别

发布于 2024-10-05 18:59:37 字数 2513 浏览 0 评论 0原文

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 --leak-check=full 编译和运行的 3 种不同方法。

非常感谢您的任何建议。

#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);
    }
}
gcc 4.5.1 c89

I have written this source code for my better understanding of malloc and calloc.

I understand, but just have a few questions.

dev = malloc(number * sizeof *devices);

is equal to this calloc. I am not concerned about clearing the memory.

dev = calloc(number, sizeof *devices);

What is that exactly, compared to doing this 5 times in a while loop:

dev = malloc(sizeof *devices);

I guess the first one and the second is creating a pointer to 5 struct device. And the third is creating a single pointer to a struct device?

My program illustrates this 3 different methods compiled and ran with valgrind --leak-check=full.

Many thanks for any advice.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

后eg是否自 2024-10-12 18:59:37

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

希望这有帮助。

calloc(a,b) and malloc(a*b) are equivalent except for the possibility of arithmetic overflow or type issues, and the fact that calloc ensures the memory is zero-byte-filled. Either allocated memory that can be used for an array of a elements each of size b (or vice versa). On the other hand, calling malloc(b) a times will results in a individual objects of size b which can be freed independently and which are not in an array (though you could store their addresses in an array of pointers).

Hope this helps.

别闹i 2024-10-12 18:59:37

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

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

就是这样。

malloc(n) allocates n bytes plus padding and overhead.

calloc(m, n) allocates m*n bytes plus padding and overhead, and then zero's the memory.

That's it.

记忆之渊 2024-10-12 18:59:37

为清楚起见进行了编辑

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

第一个 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 个指针中的每一个都必须单独释放

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

edited for clarity

  • I guess the first one and the second is creating a pointer to 5 struct device. And the third is creating a single pointer to a struct device?

The first one malloc(number * sizeof(*devices)) would allocate enough memory to store number of Devices. As others have mentioned, you can treat this block like an array of Device. The pointer you get back will point to the beginning of the block.

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

The second one that uses calloc does the same thing, while also initializing the memory to 0. Again, you can use treat the block like an array of Device.

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

The third one, looping 5 times, would result in 5 different pointers to 5 different blocks large enough to store one Device each. This also means each of the 5 pointers has to be free'ed individually.

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]);
}
榕城若虚 2024-10-12 18:59:37

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

The first two create an array of 5 devices in contiguous memory. The last malloc, done five times, will create 5 individual devices which are not guaranteed to be in contiguous memory.

—━☆沉默づ 2024-10-12 18:59:37

程序中的所有三个循环一次仅使用一个 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);

All three loops in your program use only one struct Devices object at a time. The later ones allocate extra memory as though they are going to use multiple objects, but then keep overwriting the beginning of that memory. If you tried to use the object with ID 1 after setting up the object with ID 2, you would find there is no longer any object with ID 1.

Instead, you could do something like this to treat the allocated memory as an array of structs:

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);
无畏 2024-10-12 18:59:37

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

Look at an implementation of calloc to see the differences. It's probably something like this:

// 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;
}
坏尐絯 2024-10-12 18:59:37

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

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

As you point out, calloc zeroes out the memory is allocates, while malloc doesn't.

Your examples 1 & 2 each allocate a single contiguous block of five structs (and returns a pointer to that block), whereas example 3 allocates five separate blocks of one struct each (and gives you five pointers unrelated to one another.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文