简体   繁体   中英

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:

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

Also, as I want this array to be of any size, I am using 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.

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.

Any ideas? I'm almost positive that it involves some misuse of malloc on my part.

1) cJSON_GetArraySize(items) returns an element count - you need the size of the object factored in: malloc(cJSON_GetArraySize(items) * sizeof(StatusItem))

2) a StatusItem structure doesn't have memory for the actual string - only a pointer to a string. You can use strdup() to allocate and copy a string.

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:

// 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.

  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.

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.

In addition, malloc takes a number of bytes, not elements. 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:

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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