2013-06-03 2 views
2

Je tente de faire un tableau de la structure que je avez appelé StatusItem, qui ressemble à ceci:En utilisant malloc avec une structure et strcpy

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

Aussi, comme je veux ce tableau pour être de toute taille J'utilise malloc. Ainsi, le tableau est défini comme tel:

StatusItem* statusItem = NULL; 

(son, puis transmis à la fonction qui récupère toutes les valeurs comme suit.)

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

Il y a un code venir qui implique la bibliothèque cjson à obtenir les valeurs de chaîne de name, index et optional dans les variables référencées ci-dessus, et ils sont stockés dans le champ valuestring de ces variables.

J'ai vérifié que tout ce qui concerne la bibliothèque cJSON fonctionne correctement et renvoie les valeurs correctes, mais le programme ne peut pas accéder ou stocker des valeurs dans le tableau statusItems.

Des idées? Je suis presque certain que cela implique une mauvaise utilisation de malloc de ma part.

+0

oublié la boucle for dans le code, l'a ajouté maintenant. – Nealon

Répondre

0

Pour éviter d'avoir à utiliser strdup() ce qui est un peu «messier» car il laisse la mémoire libre à l'appelant au lieu de prendre soin de tout lui-même, j'ai modifié ma structure existante comme suit:

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

Cela permet 32 ​​octets pour le nom et l'index, ce qui devrait être plus que suffisant. Auparavant, les champs structures ne pointaient sur rien, ce qui provoquait l'erreur lors de la tentative de copie vers cet emplacement. maintenant, il y a une mémoire vide (ou ordure) attendant que la chaîne soit placée dedans.

Cela permet strcpy() d'être encore utilisé, et permet une mise en œuvre globale de nettoyage.

2

Deux mésusages repéré:

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

  2. Vous n'allouent pas de mémoire pour les membres de la structure - vous êtes strcpy() à accepter d'pointeurs non initialisées, de sorte que votre programme appelle un comportement non défini .

Edit: en fait trois:

malloc(cJSON_GetArraySize(items)); 

n'alloue pas assez de mémoire car il est pas de la magie, et il ne sait pas vous réserver sizeof(StatusItem) octets de mémoire, vous devez donc multiplier le taille d'allocation par sizeof(StatusItem), ou mieux, par sizeof(*statusItem) pour la sécurité.

+0

1. Il me donne une erreur sans la distribution. 2. comment j'irais à ce sujet? – Nealon

+0

@Nealon Ensuite, compilez votre code C avec un compilateur C et ** jamais essayer de compiler du code C avec un compilateur C++, ** 2. 'statusItem [i] .name = malloc (128);' (ou autre) –

+0

I utilise un compilateur C avez toujours l'erreur – Nealon

0

En outre, malloc prend un certain nombre d'octets, pas d'éléments. La valeur qui lui est transmise doit être multipliée par la taille de chaque élément.

+0

'statusItem = (StatusItem *) malloc (cJSON_GetArraySize (items) * sizeof (StatusItem);' -? – Nealon

4

1) cJSON_GetArraySize(items) renvoie un nombre d'éléments - dont vous avez besoin de la taille de l'objet pris en compte: malloc(cJSON_GetArraySize(items) * sizeof(StatusItem))

2) une structure StatusItem n'a pas de mémoire pour la chaîne réelle - seulement un pointeur sur une chaîne. Vous pouvez utiliser strdup() pour allouer et copier une chaîne.

Vous voulez probablement votre code ressemble plus:

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

Bien sûr, cela signifie que vous devez également libérer les chaînes dupliquées explicitement lorsque vous libérez le tableau de StatusItem objets:

// 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); 
+0

Comment pourrais-je libérer ces chaînes dupliquées? – Nealon

+0

La seule façon dont je peux penser est de les libérer individuellement, mais c'est l'enfer et je ne sais même pas où strdup stocke les valeurs – Nealon

+0

@Nealon Oui, exactement, vous les libérez individuellement, vous ne pouvez rien faire d'autre. 'Strdup() 'fait un' malloc() 'pour les copies, donc il suffit de' free() 'sa valeur de retour aussi (mais tout ceci est dans la page man de' strdup() '). –