使用calloc分配内存和释放内存

4

gcc 4.4.4 c89

我有一个正在测试的程序。我创建了一个名为devname的struct对象,并分配内存以便填充其元素。我显示它们,然后释放已分配的内存。

然而,我遇到了以下错误:

invalid operands to binary != (have ‘struct Devices_names’ and ‘void *’)

这是我用于显示结构元素的for循环。然而,我感觉我正在测试一个空指针。

还有一个问题,释放内存时是否存在问题?

非常感谢任何建议。

#include <stdio.h>
#include <stdlib.h>

static struct Devices_names {
#define MAX_NAME_LEN 80
    int id;
    char name[MAX_NAME_LEN];
} *devname;

static void g_create_device_names(size_t devices);
static void g_get_device_names();
static void destroy_devices();

int main(void)
{
#define DEVICES 5
    g_create_device_names(DEVICES);

    g_get_device_names();

    destroy_devices();

    return 0;
}

static void g_create_device_names(size_t devices)
{
    size_t i = 0;
    devname = calloc(devices, sizeof *devname);
    if(devname == NULL) {
        exit(0);
    }

    for(i = 0; i < devices; i++) {
        devname[i].id = i;
        sprintf(devname[i].name, "device: %d", i);
    }
}

static void g_get_device_names()
{
    size_t i = 0;

    for(i = 0; devname[i] != NULL; i++) { <-- ERROR HERE
        printf("Device id --- [ %d ]\n", devname[i].id);
        printf("Device name - [ %s ]\n", devname[i].name);
    }
}

static void destroy_devices()
{
    while(devname != NULL) {
        free(devname++);
    }
}
4个回答

5

由于您只有一个分配来创建整个devname数组,因此只需要检查该数组是否为NULL,并且只需要释放该数组。当您查看devname时,每个条目实际上是一个struct Devices_names,而不是指针,因此无法以任何有意义的方式与NULL进行比较或释放。在这种情况下,您将需要一个单独的变量来跟踪有多少个条目:

for (i = 0; i < devname_count; i++) {
    printf("Device id --- [ %d ]\n", devname[i].id);
    printf("Device name - [ %s ]\n", devname[i].name);
}

...

free(devname);
devname = NULL;
devname_count = 0;

当我执行以下代码 devname = calloc(devices, sizeof *devname) 时,我认为我在堆上创建了5个devname对象。因此,我需要释放它们中的所有5个。但是,您是说只有一个分配的对象吗?谢谢。 - ant2009
3
您正在创建五个对象的空间,但实际上只分配了一个连续的块。一个好的经验法则是每次调用malloc()calloc()都应该与一次free()对应。 - Justin Spahr-Summers
谢谢,我会记住的。听起来是个很容易遵守的规则。 - ant2009

2

devname[i] 不是一个指针,而是一个 struct Devices_names 结构体,因此这个比较没有意义。


1

你写代码的地方:

for(i = 0; devname[i] != NULL; i++) { <-- ERROR HERE

你正在针对 Device_names 的实例进行 NULL 测试,而不是指针。如果你有一个指向 Device_names 的指针数组,那就没问题了。

另一个问题是,你只分配了一个 Device_names,所以你没有它们的数组。


1

在使用calloc之后,您只需要测试返回的指针是否不为空(并且calloc调用成功)。

但是一旦您分配了一个数组,您无法确定分配中有多少个项目,因为只有指向它的指针,因此devname[i]!= NULLdevname + i!= NULL都不起作用,尽管第二个会编译。只有环境或RTL知道这一点。这是*alloc分配和静态声明之间的巨大区别(即使它是C99中引入的可变大小)。因此,您需要在其他地方存储分配的数组的大小。

还要记住,使用单个calloc()分配的数组(或任何其他内存块)应使用与malloc返回的相同指针进行单个free()调用。将任何其他指针传递给free()会导致未定义的行为(通常是失败)。

因此,您的代码应该是:

static struct Devices_names {
#define MAX_NAME_LEN 80
    int id;
    char name[MAX_NAME_LEN];
} *devname;
size_t devicecount;

...

    devname = calloc(devices, sizeof *devname);
    if(devname == NULL) {
        exit(0);
    }
    devicecount = devices;

...

    for(i = 0; i<devicecount; i++) { // <-- no error more here

...

static void destroy_devices()
{
    free(devname);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接