2

我正在尝试制作一个名为 的结构数组,StatusItem如下所示:

typedef struct 
{
    char* name;
    char* index;
    int optional;
} StatusItem;

此外,由于我希望此数组具有任何大小,因此我正在使用malloc. 所以数组定义如下:

StatusItem* statusItem = NULL;

(然后将其传递给检索所有值的函数,如下所示。)

statusItem = (StatusItem*)malloc(cJSON_GetArraySize(items));

...

for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
    strcpy(statusItem[i].name,name->valuestring);
    strcpy(statusItem[i].index,index->valuestring);
    if(!parseInt(optional->valuestring, &statusItem[i].optional));
    {
         goto cleanup;
    }
}

有一些代码涉及 cJSON 库获取 的字符串值nameindexoptional放入上面引用的变量中,并且它们存储在valuestring这些变量的字段中。

我检查了涉及 cJSON 库的所有内容都可以正常工作,并返回正确的值,但程序无法访问或存储statusItems数组中的值。

有任何想法吗?我几乎可以肯定它涉及malloc我的一些滥用。

4

4 回答 4

4

1)cJSON_GetArraySize(items)返回一个元素计数 - 您需要考虑对象的大小:malloc(cJSON_GetArraySize(items) * sizeof(StatusItem))

2)StatusItem结构没有实际字符串的内存 - 只有一个指向字符串的指针。您可以使用strdup()来分配和复制字符串。

您可能希望您的代码看起来更像:

statusItem = (StatusItem*)malloc(cJSON_GetArraySize(items) * sizeof(StatusItem));

...

for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
    statusItem[i].name = strdup(name->valuestring);
    statusItem[i].index = strdup(index->valuestring);
    if(!parseInt(optional->valuestring, &statusItem[i].optional));
    {
         goto cleanup;
    }
}

当然,这意味着您还必须在释放StatusItem对象数组时显式释放重复的字符串:

// to free the statusItem array, and the various strings it refers to:

for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
    free(statusItem[i].name);
    free(statusItem[i].index);
}

free(statusItem);
于 2013-06-03T19:26:32.423 回答
2

发现两个误用:

  1. 不要强制转换 的返回值malloc(),这是危险和多余的。

  2. 您不会为结构的成员分配任何内存 - 您正在strcpy()访问未初始化的指针,因此您的程序会调用未定义的行为。

编辑:实际上三个:

malloc(cJSON_GetArraySize(items));

没有分配足够的内存,因为它不是魔术,并且它不知道您正在保留内存字节,因此为了安全起见sizeof(StatusItem),您必须将分配大小乘以sizeof(StatusItem),甚至更好。sizeof(*statusItem)

于 2013-06-03T19:22:27.577 回答
0

此外, malloc 需要一些字节,而不是元素。传递给它的值必须乘以每个元素的大小。

于 2013-06-03T19:24:40.547 回答
0

为了避免不得不使用strdup()which 有点“混乱”,因为它将内存的释放留给调用者而不是自己处理所有事情,我修改了我现有的结构如下:

typedef struct 
{
    char name[32];
    char index[32];
    int optional;
} StatusItem;

这允许 32 个字节用于名称和索引,这应该绰绰有余。以前,结构字段没有指向任何内容,这在尝试复制到该位置时导致错误。现在,有空(或垃圾)内存在等待放入字符串。

这允许strcpy()仍然使用,并允许整体更清洁的实现。

于 2013-06-03T19:57:37.710 回答