简体   繁体   English

在结构和strcpy中使用malloc

[英]Using malloc with a structure and strcpy

I'm attempting to make an array of the structure I made called StatusItem , which looks like this: 我正在尝试制作一个名为StatusItem的结构的数组,如下所示:

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

Also, as I want this array to be of any size, I am using malloc . 另外,由于我希望此数组具有任意大小,因此我正在使用malloc So the array is defined as such: 因此,数组的定义如下:

StatusItem* statusItem = NULL;

(its then passed to function which retrieves all the values as follows.) (然后将其传递给函数,该函数将按如下所示检索所有值。)

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

There's come code that involves the cJSON library in getting the string values of name , index and optional into the variables referenced above, and they are stored in the valuestring field of those variables. 有涉及cJSON库的代码,用于将nameindexoptional的字符串值获取到上面引用的变量中,并将它们存储在这些变量的valuestring字段中。

I have checked that everything involving the cJSON library works fine, and returns the correct values, but the program is unable to access or store values in the statusItems array. 我检查了涉及cJSON库的所有内容,都可以正常工作,并返回正确的值,但是该程序无法访问或将值存储在statusItems数组中。

Any ideas? 有任何想法吗? I'm almost positive that it involves some misuse of malloc on my part. 我几乎肯定,这涉及到我对malloc一些滥用。

1) cJSON_GetArraySize(items) returns an element count - you need the size of the object factored in: malloc(cJSON_GetArraySize(items) * sizeof(StatusItem)) 1) cJSON_GetArraySize(items)返回元素计数-您需要考虑以下因素的对象大小: malloc(cJSON_GetArraySize(items) * sizeof(StatusItem))

2) a StatusItem structure doesn't have memory for the actual string - only a pointer to a string. 2) StatusItem结构没有用于实际字符串的内存-只有指向字符串的指针。 You can use strdup() to allocate and copy a string. 您可以使用strdup()分配和复制字符串。

You probably want your code to look more like: 您可能希望代码看起来更像:

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

Of course this means that you also have to free the duplicated strings explicitly when you free the array of StatusItem objects: 当然,这意味着在释放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);

Two misuses spotted: 发现了两个误用:

  1. Don't cast the return value of malloc() , it's dangerous and superfluous. 不要malloc()的返回值,这是危险且多余的。

  2. You don't allocate any memory for the members of the structure - you're strcpy() ing to uninitialized pointers, so your program invokes undefined behavior. 您没有为结构的成员分配任何内存-您正在对未初始化的指针进行strcpy() ,因此您的程序将调用未定义的行为。

Edit: actually three: 编辑:实际上三个:

malloc(cJSON_GetArraySize(items));

doesn't allocate enough memory since it's not magic and it doesn't know you're reserving sizeof(StatusItem) bytes of memory, thus you have to multiply the allocation size by sizeof(StatusItem) , or even better, by sizeof(*statusItem) for safety. 没有分配足够的内存,因为这不是魔术,也不知道您要保留sizeof(StatusItem)个字节的内存,因此您必须将分配sizeof(StatusItem)sizeof(StatusItem) ,甚至更好地乘以sizeof(*statusItem)以确保安全。

In addition, malloc takes a number of bytes, not elements. 另外,malloc占用许多字节,而不是元素。 The value passed to it must be multiplied by the size of each element. 传递给它的值必须乘以每个元素的大小。

To avoid having to use strdup() which is a little 'messier' because it leaves the freeing of the memory up to the caller instead of taking care of everything itself, I modified my existing structure as follows: 为了避免使用有点“麻烦”的strdup() ,因为它将内存留给调用者,而不是自己处理所有事情,我对现有结构进行了如下修改:

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

This allows 32 bytes for the name and index, which should be more than enough. 这样可以为名称和索引提供32个字节,这应该绰绰有余。 Before, the structures fields were pointing to nothing, which was causing the error when trying to copy to that location. 以前,结构字段没有指向任何内容,这在尝试复制到该位置时导致错误。 now, there is empty (or junk) memory waiting for the string to be placed in. 现在,有空(或垃圾)内存,等待放入字符串。

This allows for strcpy() to still be used, and allows for an overall cleaner implementation. 这允许仍使用strcpy() ,并允许整体上更干净的实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM