2010-11-30 4 views
3

gcc 4.4.4 c89allocation de mémoire à l'aide de calloc et de libération

J'ai un programme que je suis en train de tester. Je crée un objet struct appelé devname et alloue de la mémoire pour que je puisse remplir les éléments. Je les affiche et libère ensuite la mémoire allouée.

Cependant, je reçois l'erreur suivante:

invalid operands to binary != (have ‘struct Devices_names’ and ‘void *’) 

qui est dans ma boucle pour afficher les éléments de structure. Cependant, j'ai l'impression de tester un pointeur NULL.

Juste une question supplémentaire, y at-il un problème avec le libre?

Un grand merci pour tous les conseils,

#include <stdio.h> 
#include <stdlib.h> 

static struct Devices_names { 
#define MAX_NAME_LEN 80 
    int id; 
    char name[MAX_NAME_LEN]; 
} *devname; 

static void g_create_device_names(size_t devices); 
static void g_get_device_names(); 
static void destroy_devices(); 

int main(void) 
{ 
#define DEVICES 5 
    g_create_device_names(DEVICES); 

    g_get_device_names(); 

    destroy_devices(); 

    return 0; 
} 

static void g_create_device_names(size_t devices) 
{ 
    size_t i = 0; 
    devname = calloc(devices, sizeof *devname); 
    if(devname == NULL) { 
     exit(0); 
    } 

    for(i = 0; i < devices; i++) { 
     devname[i].id = i; 
     sprintf(devname[i].name, "device: %d", i); 
    } 
} 

static void g_get_device_names() 
{ 
    size_t i = 0; 

    for(i = 0; devname[i] != NULL; i++) { <-- ERROR HERE 
     printf("Device id --- [ %d ]\n", devname[i].id); 
     printf("Device name - [ %s ]\n", devname[i].name); 
    } 
} 

static void destroy_devices() 
{ 
    while(devname != NULL) { 
     free(devname++); 
    } 
} 

Répondre

4

Puisque vous avez seulement une allocation pour créer l'ensemble devname tableau, il vous suffit de vérifier que tableau pour NULL, et seulement besoin de libérer qu'un tableau. Comme vous regardez à travers devname, chaque entrée est en fait un struct Devices_names, pas un pointeur, donc il ne peut pas être comparé avec NULL ou libéré de manière significative. Dans ce cas, vous aurez besoin d'une variable distincte qui suit combien entrées il y a:

for (i = 0; i < devname_count; i++) { 
    printf("Device id --- [ %d ]\n", devname[i].id); 
    printf("Device name - [ %s ]\n", devname[i].name); 
} 

... 

free(devname); 
devname = NULL; 
devname_count = 0; 
+0

Quand je l'ai fait la devname suivante = calloc (dispositifs, sizeof * devname). Je pensais que je créais 5 objets devname sur le tas. Donc je devrais libérer tous les 5 d'entre eux. Cependant, dites-vous qu'il n'y a qu'un seul objet alloué? Merci. – ant2009

+1

Vous créez * espace * pour cinq objets, mais vous n'allouez qu'un seul bloc contigu. En règle générale, chaque appel à 'malloc()' ou 'calloc()' devrait correspondre exactement à un appel à 'free()'. –

+0

Merci, je m'en souviendrai. Cela ressemble à une règle facile à suivre. – ant2009

2

devname[i] n'est pas un pointeur est un struct Devices_names, par conséquent, la comparaison n'a pas de sens.

1

où vous écrivez:

for(i = 0; devname[i] != NULL; i++) { <-- ERROR HERE 

vous testez sur une instance de NULL Device_names, pas un pointeur. Ce serait bien si vous aviez un tableau de pointeurs sur Device_names.

L'autre problème est que vous n'allouez qu'un seul Device_names, vous n'avez donc pas de tableau.

1

Après calloc, vous devez uniquement tester que le pointeur renvoyé n'est pas nul (et calloc appel réussi).

Mais une fois que vous calloc ATED un tableau que vous ne pouvez pas déterminer le nombre d'éléments dans l'allocation ayant seulement pointeur, donc ni devname[i] != NULL, ni devname+i != NULL ne fonctionnera pas, barbante deuxième compilera. Seul l'environnement ou RTL le sait. Et il s'agit d'une grande différence entre l'allocation *alloc et la déclaration statique (même si elle est de taille variable telle qu'introduite dans C99). Vous avez donc besoin de stocker la taille du tableau alloué ailleurs.

Rappelez-vous, array (ou tout autre morceau de mémoire) alloué avec calloc() unique doit être libéré avec appel unique free() avec SAME pointeur tel que retourné par malloc. Le passage d'un autre pointeur à free() provoque un comportement indéfini (ce qui est souvent FAIL).

Donc, votre code devrait être:

static struct Devices_names { 
#define MAX_NAME_LEN 80 
    int id; 
    char name[MAX_NAME_LEN]; 
} *devname; 
size_t devicecount; 

... 

    devname = calloc(devices, sizeof *devname); 
    if(devname == NULL) { 
     exit(0); 
    } 
    devicecount = devices; 

... 

    for(i = 0; i<devicecount; i++) { // <-- no error more here 

... 

static void destroy_devices() 
{ 
    free(devname); 
}