使用带结构和strcpy的malloc

时间:2013-06-03 19:19:45

标签: c struct malloc strcpy cjson

我正在尝试创建一个名为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的字符串值放入上面引用的变量中,并将它们存储在{{1}中这些变量的字段。

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

有什么想法吗?我几乎是肯定的,这涉及我statusItems的一些误用。

4 个答案:

答案 0 :(得分: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);

答案 1 :(得分:2)

发现了两个误用:

  1. Don't cast the return value of malloc(), it's dangerous and superfluous.

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

  3. 编辑:实际上是三个:

    malloc(cJSON_GetArraySize(items));
    

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

为了避免使用strdup()这有点'杂乱',因为它让内存释放到调用者而不是自己处理所有事情,我修改了我现有的结构如下:

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

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

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